I followed this guide to try and embed 2 images on Emails
this is my code written in C# for a console application:
the ExecuteSendMailEx procedure:
public void ExecuteSendMailEx(AccesBase accesBase, string From, string Subjet, bool Format, string EmailLogoHeader, string EmailLogoFooter, string ReplyTo, string ReturnPath, string BodyHtml, string BodyText, string Destinataire, string IdLangage, string CopieCachee, string PJ, string SMTP, string SMTPPORT, string SMTPLOGIN, string SMTPPWD, ref int RTN)
{
try
{
Log.Information("ENVOI_Constructor ExecuteSendMailEx has begun");
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse(From));
email.To.Add(MailboxAddress.Parse(Destinataire));
email.ReplyTo.Add(MailboxAddress.Parse(ReplyTo));
if (!string.IsNullOrEmpty(CopieCachee))
email.Bcc.Add(MailboxAddress.Parse(CopieCachee));
email.Subject = Subjet;
email.Sender = (MailboxAddress.Parse(SMTPLOGIN));
var currentDirectory = Directory.GetCurrentDirectory();
var parentDirectory = Directory.GetParent(currentDirectory).FullName;
var filesDirectory = parentDirectory + "\\Files";
var builder = new BodyBuilder();
if (EmailLogoHeader != "" && EmailLogoFooter != "")
{
var imageHead = builder.LinkedResources.Add(filesDirectory + "\\" + EmailLogoHeader);
imageHead.ContentId = MimeUtils.GenerateMessageId();
var imageFoot = builder.LinkedResources.Add(filesDirectory + "\\" + EmailLogoFooter);
imageFoot.ContentId = MimeUtils.GenerateMessageId();
builder.HtmlBody = string.Format(#"<img src='cid:{0}'><br>{1}<br><img src='cid:{2} '>", imageHead.ContentId, BodyHtml, imageFoot.ContentId);
}
else if (EmailLogoFooter != "" && EmailLogoHeader == "")
{
var imageFoot = builder.LinkedResources.Add(filesDirectory + "\\" + EmailLogoFooter);
imageFoot.ContentId = MimeUtils.GenerateMessageId();
builder.HtmlBody = string.Format(#"{0}<br><img src='cid={1}'>", BodyHtml, imageFoot.ContentId);
}
else if (EmailLogoHeader != "" && EmailLogoFooter == "")
{
var imageHead = builder.LinkedResources.Add(filesDirectory+"\\" + EmailLogoHeader);
imageHead.ContentId = MimeUtils.GenerateMessageId();
builder.HtmlBody = string.Format(#"<img src='cid:{0}'><br>{1}", imageHead.ContentId, BodyHtml);
}
else
builder.HtmlBody = BodyHtml;
builder.TextBody = BodyText ;
if (Format == false)
{
builder.Attachments.Add(addImage(filesDirectory + EmailLogoHeader));
builder.Attachments.Add(addImage(filesDirectory + EmailLogoFooter));
}
email.Body = Format == false ? new TextPart(TextFormat.Text) { Text = builder.TextBody } : new TextPart(TextFormat.Html){ Text= builder.HtmlBody };
// send email
var smtp = new MailKit.Net.Smtp.SmtpClient();
smtp.Connect(SMTP, Int32.Parse(SMTPPORT), SecureSocketOptions.StartTls);
smtp.Authenticate(SMTPLOGIN, SMTPPWD);
smtp.Send(email);
smtp.Disconnect(true);
}
catch (Exception ex) { Log.Error(ex.Message + " : " + ex.InnerException + " - ENVOI_Constructor: ExecuteSendMailEx Method"); }
}
obviously, my first lines of the code are:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Web;
using TP;
using System.Net;
using System.Net.Mail;
using MimeKit;
using MimeKit.Text;
using MailKit.Net.Smtp;
using MailKit.Security;
using Serilog;
using System.Drawing;
using System.IO;
using MimeKit.Utils;
expected behavior: I tried everything to embed images to Emails sent with MailKit, but they always come out as
all variables contain correct values like SMTP hosting the Exchange server address or SMTPPORT containing the port, every variable is named like its meaning,
the EmailHeaderLogo & EmailFooterLogo contain the pathes like Mail\image.jpg,
I navigated to the parent folder because the files are on the parent folder and inside the path that exist on the variable,
sorry that the code may seem French, I'm not french but where I'm working is a french international company,
if you want any additional information, don't hesitate to ask me,
and thank you
The problem is that you are setting the message body incorrectly.
Replace the following line:
email.Body = Format == false ? new TextPart(TextFormat.Text) { Text = builder.TextBody } : new TextPart(TextFormat.Html){ Text= builder.HtmlBody };
with this:
email.Body = builder.ToMessageBody();
I don't understand Format is supposed to do, but it looks like if Format is false, then you want only plain-text?
If so, you'll want to change your code to the following:
public void ExecuteSendMailEx(AccesBase accesBase, string From, string Subjet, bool Format, string EmailLogoHeader, string EmailLogoFooter, string ReplyTo, string ReturnPath, string BodyHtml, string BodyText, string Destinataire, string IdLangage, string CopieCachee, string PJ, string SMTP, string SMTPPORT, string SMTPLOGIN, string SMTPPWD, ref int RTN)
{
try
{
Log.Information("ENVOI_Constructor ExecuteSendMailEx has begun");
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse(From));
email.To.Add(MailboxAddress.Parse(Destinataire));
email.ReplyTo.Add(MailboxAddress.Parse(ReplyTo));
if (!string.IsNullOrEmpty(CopieCachee))
email.Bcc.Add(MailboxAddress.Parse(CopieCachee));
email.Subject = Subjet;
email.Sender = (MailboxAddress.Parse(SMTPLOGIN));
var currentDirectory = Directory.GetCurrentDirectory();
var parentDirectory = Directory.GetParent(currentDirectory).FullName;
var filesDirectory = Path.Combine(parentDirectory, "Files");
var builder = new BodyBuilder();
if (Format)
{
// If we have any headers or footers, inject those into the HTML body
if (!string.IsNullOrEmpty(EmailLogoHeader) && !string.IsNullOrEmpty(EmailLogoFooter))
{
var imageHead = builder.LinkedResources.Add(Path.Combine(filesDirectory, EmailLogoHeader));
imageHead.ContentId = MimeUtils.GenerateMessageId();
var imageFoot = builder.LinkedResources.Add(Path.Combine(filesDirectory, EmailLogoFooter));
imageFoot.ContentId = MimeUtils.GenerateMessageId();
builder.HtmlBody = string.Format(#"<img src='cid:{0}'><br>{1}<br><img src='cid:{2} '>", imageHead.ContentId, BodyHtml, imageFoot.ContentId);
}
else if (!string.IsNullOrEmpty(EmailLogoFooter))
{
var imageFoot = builder.LinkedResources.Add(Path.Combine(filesDirectory, EmailLogoFooter));
imageFoot.ContentId = MimeUtils.GenerateMessageId();
builder.HtmlBody = string.Format(#"{0}<br><img src='cid={1}'>", BodyHtml, imageFoot.ContentId);
}
else if (!string.IsNullOrEmpty(EmailLogoHeader))
{
var imageHead = builder.LinkedResources.Add(Path.Combine(filesDirectory, EmailLogoHeader));
imageHead.ContentId = MimeUtils.GenerateMessageId();
builder.HtmlBody = string.Format(#"<img src='cid:{0}'><br>{1}", imageHead.ContentId, BodyHtml);
}
else
{
builder.HtmlBody = BodyHtml;
}
}
else
{
// No HTML body is desired, so just add the header and footer images as attachments instead.
if (!string.IsNullOrEmpty(EmailLogoHeader))
builder.Attachments.Add(Path.Combine(filesDirectory, EmailLogoHeader));
if (!string.IsNullOrEmpty(EmailLogoFooter))
builder.Attachments.Add(Path.Combine(filesDirectory, EmailLogoFooter));
}
builder.TextBody = BodyText;
email.Body = builder.ToMessageBody();
// send email
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
{
smtp.Connect(SMTP, Int32.Parse(SMTPPORT), SecureSocketOptions.StartTls);
smtp.Authenticate(SMTPLOGIN, SMTPPWD);
smtp.Send(email);
smtp.Disconnect(true);
}
}
catch (Exception ex)
{
Log.Error(ex.Message + " : " + ex.InnerException + " - ENVOI_Constructor: ExecuteSendMailEx Method");
}
}
Note: I took the liberty of changing your code to use string.IsNullOrEmpty() instead of doing a direct comparison with "" as well as fixing your code to use Path.Combine(). You should really get into the habit of using Path.Combine(), especially, since it will help make your code portable to non-Windows platforms if you ever want to run your code on .NET Core (where it may run on a Linux or Mac).
I am trying to connect to IBM remote MQ and I am facing this System.DllNotFoundException error . I built a simple console application using C# and wrote MQ connection code .
My code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IBM.WMQ;
using System.Diagnostics;
namespace MQMessageSender
{
public class MQTest
{
public static void Main()
{
ConnectMQ();
}
public static int ConnectMQ()
{
MQQueueManager queueManager;
MQQueue queue;
MQMessage queueMessage;
MQPutMessageOptions queuePutMessageOptions;
MQGetMessageOptions queueGetMessageOptions;
string QueueName;
string QueueManagerName;
string ChannelInfo;
string channelName;
string PortNumber;
string transportType;
string connectionName;
string message;
QueueManagerName = "******";
QueueName = "********";
ChannelInfo = "********/TCP/********(****)";
PortNumber = "****";
char[] separator = { '/' };
string[] ChannelParams;
ChannelParams = ChannelInfo.Split(separator);
channelName = ChannelInfo;
transportType = ChannelParams[1];
connectionName = ChannelParams[2];
String strReturn = "";
try
{
queueManager = new MQQueueManager(QueueManagerName,
channelName, connectionName);
strReturn = "Connected Successfully";
}
catch (MQException exp)
{
strReturn = "Exception: " + exp.Message;
}
Console.WriteLine(strReturn);
Console.WriteLine("Press any key to continue . . .");
Console.ReadLine();
return 0;
}
}
}
Can anyone help me with this . Mostly try block is generating this error . Any kind of information will help . Please help . Error screenshot is attached .
I have a small application that checks all of the logs in a directory named after domain usernames and generates a results file with each username and the relevant first and surname for that user.
The console is outputting the full list successfully but it seems that the StreamWriter is stopping halfway through an entry.
The number of characters it writes before stopping is consistent - to some extent. If I set the outputstring to include more characters between the two variables filename and the result from FindNameFromUsername then the character count with or without spaces changes so I've ruled that out.
Any ideas as to why the console outputs the line but the streamwriter doesn't?
Code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.ActiveDirectory;
namespace Filename_Finder
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please insert the full directory path. All filenames in the root of this folder will be logged to one file.");
string outputFilename = "results.txt";
string userPath = Console.ReadLine();
string domain = "ou=users,dc=domain,dc=local";
try
{
string outputFilepath = userPath + outputFilename;
string[] filepaths = Directory.GetFiles(userPath);
using (StreamWriter file = new StreamWriter(outputFilepath, false))
{
for (int i = 0; i < filepaths.Length; i++)
{
string filepath = filepaths[i];
char split = '.';
string filename = filepath.Remove(0, userPath.Count());
if (filename != outputFilename)
{
int extensionBegins = filename.LastIndexOf(split);
filename = filename.Remove(extensionBegins);
string outputstring = (filename + " -- " + FindNameFromUsername(filename, domain));
Console.WriteLine(outputstring);
file.WriteLine(outputstring);
}
}
Console.ReadLine();
}
}
catch (Exception e) { Console.WriteLine(e); Console.ReadLine(); }
}
public static string FindNameFromUsername(string username, string domainScope)
{
string connectionPrefix = "LDAP://" + domainScope;
DirectoryEntry entry = new DirectoryEntry(connectionPrefix);
DirectorySearcher searcher = new DirectorySearcher(entry);
string filter = "(&(objectClass=user)";
filter += "(|(sAMAccountName=" + username + ")))";
searcher.Filter = filter;
SearchResult result = searcher.FindOne();
string resultValue = string.Empty;
DirectoryEntry obj = result.GetDirectoryEntry();
resultValue = "" + obj.Properties["givenName"].Value + " " + obj.Properties["sn"].Value;
if (resultValue == " ") { resultValue = username; }
entry.Close(); entry.Dispose();
obj.Close(); obj.Dispose();
searcher.Dispose();
return resultValue;
}
}
}
Your Console.ReadLine() will pause the execution and I'm guessing that's where you are checking the content of your file.
However, the file won't be flushed and closed until the StreamWriter is being disposed. That happens at the end of the using block, i.e. after your ReadLine() statement.
Take a look at this question.
You might find useful setting your StreamWriter.AutoFlush property to true in order to get similar behavior to the corresponding Console method, like this:
using (var file = new StreamWriter(outputFilepath, false) { AutoFlush = true })
I am working on a post redirect for a payment provider and trying to pass form data to their secure URL.
I am doing this in kentico 8 by using their custom payment gateway method as shown here https://docs.kentico.com/display/K8/Creating+a+custom+payment+gateway
So in the custom payment class I prepared the data to be passed to the payment provider in a 'Form' format with hidden fields using this tutorial http://www.codeproject.com/Articles/37539/Redirect-and-POST-in-ASP-NET
However I am not able to figure out on how to redirect to the secure URL with the form data?
Here is my code so far.
I have tried Response.Redirect however it is a GET function instead of POST.
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using CMS;
using CMS.Base;
using CMS.EcommerceProvider;
using CMS.Helpers;
using System.Security.Cryptography;
using System.Web;
using System.Web.Security;
using System.Text;
using System.IO;
using System.Net;
using System.Web.UI;
[assembly: RegisterCustomClass("CustomGateway", typeof(CustomGateway))]
public class CustomGateway : CMSPaymentGatewayProvider
{
/// <summary>
/// Process payment.
/// </summary>
public override void ProcessPayment()
{
// Get payment gateway url
string url = "https://epage.payandshop.com/epage.cgi";
if (url != "")
{
NameValueCollection postData = getRealexData();
RedirectAndPOST(url, postData);
}
else
{
// Show error message - payment gateway url not found
ErrorMessage = "Unable to finish payment: Payment gateway url not found.";
// Update payment result
PaymentResult.PaymentDescription = ErrorMessage;
PaymentResult.PaymentIsCompleted = false;
// Update order payment result in database
UpdateOrderPaymentResult();
}
}
public static void RedirectAndPOST(string destinationUrl, NameValueCollection data)
{
//Prepare the Posting form
string strForm = PreparePOSTForm(destinationUrl, data);
HttpContext.Current.Response.Write(strForm);
HttpContext.Current.Response.End();
}
private static String PreparePOSTForm(string url, NameValueCollection data)
{
//Set a name for the form
string formID = "PostForm";
//Build the form using the specified data to be posted.
StringBuilder strForm = new StringBuilder();
strForm.Append("<form id=\"" + formID + "\" name=\"" +
formID + "\" action=\"" + url +
"\" method=\"POST\">");
foreach (string key in data)
{
strForm.Append("<input type=\"hidden\" name=\"" + key +
"\" value=\"" + data[key] + "\">");
}
strForm.Append("</form>");
//Build the JavaScript which will do the Posting operation.
StringBuilder strScript = new StringBuilder();
strScript.Append("<script language=\"javascript\">");
strScript.Append("var v" + formID + " = document." +
formID + ";");
strScript.Append("v" + formID + ".submit();");
strScript.Append("</script>");
//Return the form and the script concatenated.
//(The order is important, Form then JavaScript)
return strForm.ToString() + strScript.ToString();
}
public NameValueCollection getRealexData()
{
//format the date expected by Realex
string timestamp = RealexDateFormatter.DateFormatForRealex();
//take the MerchantID and Shared Secret from the web.config
string merchantid = ConfigurationManager.AppSettings["RealexMerchantID"];
string secret = ConfigurationManager.AppSettings["RealexSecret"];
// Order Info
int orderid = ShoppingCartInfoObj.OrderId;
string stringorderid = Convert.ToString(orderid);
string curr = ShoppingCartInfoObj.Currency.CurrencyCode;
double amount = ShoppingCartInfoObj.TotalPrice;
amount = Convert.ToInt32(amount);
string prepareMD5 = timestamp + "." + merchantid + "." + orderid + "." + amount + "." + curr;
//generate the md5 Hash
MD5 md5 = new MD5CryptoServiceProvider();
string temp1 = GetMD5Hash(prepareMD5);
temp1 = temp1.ToLower();
string temp2 = temp1 + "." + secret;
string md5hash = GetMD5Hash(temp2);
md5hash = md5hash.ToLower();
NameValueCollection data = new NameValueCollection();
data.Add("MERCHANT_ID", merchantid);
data.Add("ORDER_ID", stringorderid);
data.Add("CURRENCY", curr);
data.Add("AMOUNT", amount.ToString());
data.Add("TIMESTAMP", timestamp);
data.Add("MD5HASH", md5hash);
data.Add("AUTO_SETTLE_FLAG", "1");
return data;
}
public static String GetMD5Hash(String TextToHash)
{
//Check wether data was passed
if ((TextToHash == null) || (TextToHash.Length == 0))
{
return String.Empty;
}
//Calculate MD5 hash
MD5 md5 = new MD5CryptoServiceProvider();
// Create a new Stringbuilder to collect the bytes
// and create a string.
byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(TextToHash));
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
return sBuilder.ToString();
}
}
Take a look at this answer from a similar question. I would recommend using Method 3 in that answer. By creating an asynchronous call, you could wait for a response back and either redirect on a successful response with Response.Redirect(), or notify the user of any errors.
I'm trying to take a JSON response, deserialize it, and store in a localdb. Everything is working, but its not writing the data to my database. I can't seem to figure out why its not as I'm not getting any errors.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using DataFetcher.DataFieldsInClasses;
using DataFetcher.EF_Models;
using Newtonsoft.Json;
namespace DataFetcher
{
class Program
{
static void Main(string[] args)
{
var teamNames = new TeamsList();
teamNames.teamList.Sort();
for (int i = 0; i < 30; i++)
{
var cities = teamNames.teamList.ElementAt(i);
//URL for each indivual team
string URL = #"http://nhlwc.cdnak.neulion.com/fs1/nhl/league/teamroster/" + cities + "/iphone/clubroster.json";
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(URL);
HttpWebResponse response = wrGETURL.GetResponse() as HttpWebResponse;
StreamReader responseStream = new StreamReader(response.GetResponseStream());
var result = responseStream.ReadToEnd();
//var parsedInformation = JsonConvert.DeserializeObject<RootObject>(result);
foreach (var forwardData in JsonConvert.DeserializeObject<RootObject>(result).forwards)
{
//test output
Console.WriteLine(forwardData.id + " " + " " + forwardData.position + " " + forwardData.name + " " + forwardData.twitterURL + " " + forwardData.height + " " + forwardData.birthdate);
//write to database using EF
using (var _temp_Player = new DataFetcherDBEntities())
{
//var players = _temp_Player.Set<Player>();
_temp_Player.Players.Attach(new Player
{
player_id = forwardData.id,
name = forwardData.name,
age = forwardData.age,
birthdate = forwardData.birthdate,
birthplace = forwardData.birthplace,
weight = forwardData.weight,
height = forwardData.height,
number = forwardData.number,
position = forwardData.position,
imageUrl = forwardData.imageUrl,
twitterURL = forwardData.twitterURL,
twitterHandle = forwardData.twitterHandle
});
_temp_Player.SaveChanges();
}
}
}
Console.ReadKey();
}
}
}
Any tips/ideas?
P.S I'm still learning and self-taught.
*Edit, I copied the localdb to "...DataFetcher\bin\Debug\Databases" and my new error is ""Violation of PRIMARY KEY constraint 'PK__tmp_ms_x__44DA120C6655986D'. Cannot insert duplicate key in object 'dbo.Player'. The duplicate key value is (8473492).\r\nThe statement has been terminated."}"
Which doesn't make sense to me as every player has a unique ID (player_id = forwardData.id)
You need to use _temp_Player.Players.Add instead of Attach.
When you Attach, you need to set the entity state for the EF to detect that it is a new record and insert it into the database during Save Changes.