Mvc .Net.Mail: How to send email with image (logo) - c#

I am using three classes to send email but i cant to combine text email with image, or just to send image. When i get email i see empty image.
Help me to change my code so i can to send email with:
text
image
and style
public class SendService : IDistributionProvider
{
public int Send(System.Xml.Linq.XDocument recipientsData, string subject, string fromName, string fromAccount)
{
foreach (XElement element in recipientsData.Root.Elements())
{
string email = element.Element("email").Value;
string name = element.Element("name").Value;
string message = element.Element("message").Value;
bool result = EmailUtils.SendEmail(fromAccount, fromName, email, name, subject, message.Replace("\n", "<br/>"));
}
return 1;
}
public interface IDistributionProvider
{
int Send(XDocument recipientsData, string subject, string fromName,
string fromAccount);
}
public static class EmailUtils
{
private static string sendHostName;
private static int sendPort;
private static string userName;
private static string password;
private static string defaultFromEmail;
private static string defaultFromName;
static EmailUtils()
{
sendHostName = ConfigurationManager.AppSettings["sendHostName"];
sendPort = int.Parse(ConfigurationManager.AppSettings["sendPort"]);
defaultFromEmail = ConfigurationManager.AppSettings["fromEmail"];
defaultFromName = ConfigurationManager.AppSettings["fromName"];
string credential = Utils.DecryptString(ConfigurationManager.AppSettings["credential"]);
if (!string.IsNullOrEmpty(credential) && credential.Split(";".ToCharArray()).Length > 1)
{
userName = credential.Split(";".ToCharArray())[0];
password = credential.Split(";".ToCharArray())[1];
}
}
public static bool SendEmail(string toEmail, string toName, string subject, string body)
{
return SendEmail(defaultFromEmail, defaultFromName, toEmail, toName, subject, body);
}
public static bool SendEmail(string fromEmail, string fromName, string toEmail, string toName, string subject, string body)
{
try
{
if (string.IsNullOrEmpty(toEmail))
{
return false;
}
if (string.IsNullOrEmpty(toName))
{
toName = toEmail.Substring(0, toEmail.IndexOf("#"));
}
if (string.IsNullOrEmpty(fromEmail))
{
fromEmail = defaultFromEmail;
}
if (string.IsNullOrEmpty(fromName))
{
fromName = defaultFromName;
}
Message message = new Message();
message.Charset = "UTF-8";
message.Subject = Codec.RFC2047Encode(subject, "UTF-8");
message.From = new Address(fromEmail, fromName);
message.To.Add(toEmail, toName);
message.BodyHtml.Format = BodyFormat.Html;
message.BodyHtml.Charset = "UTF-8";
message.BodyHtml.Text = body;
return ActiveUp.Net.Mail.SmtpClient.SendSsl(message, sendHostName, sendPort, userName, password, SaslMechanism.Login);
}
catch
{
return false;
}
}
}
In this way I send email- just text:
string bodyEmail = "<h2>Welcome to website</h2></br><div><p>Thank for using website</p></div>";
EmailUtils.SendEmail("xxx#gmail.com","xxxx","Contact",bodyEmail);

Easiest way to do it is to inline your images using Data URIs.
You essentially inline the image into the HTML of your message. Just follow the format
data:[<MIME-type>][;charset=<encoding>][;base64]
where mime-type may be image/jpeg, charset should be ASCII, and the bytes of the image converted to base64. You can get that by reading the bytes of the image file from disk
byte[] imaeg = File.ReadAllBytes("nekkedladies.jpg");
then convert the byte array to a base 64 string
var base64Imaeg = System.Convert.ToBase64String(imaeg);
slap it together and stick it in your html (stolen from wiki)
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Nekkid Ladies" />
btw, the example image data isn't nekkid ladies. It's this:
sorry

I've actually ran into this same problem and what really helped me was this. In my case I had the html and I had to parse it out using HtmlUtilityPack. I would not recommend using the encoded string as It is not fully supported, and it makes your message bloated. The cid way is also how outlook adds images to an email. I'd add code but I think the example was good enough in my case.

Related

Sending email notification upon error in C#

I set up this try/catch and I want to send an error to my email when something goes wrong like an invalid password being entered. I know I have most of it right but I'm not getting an email when I force a change in my config file. I'm not getting any errors when I run this so I'm assuming it must be something small. Does anyone see any obvious errors I've made? Let me know if additional info is required.
Thanks in advance...learning tons of C# but no master just yet.
try
{
_arrivals = new ArrivalsService();
_configuration = new Configuration(xmlMessage);
//process summary or detail
if (_configuration.IncludeHODetails == true)
{
throw new Exception("Include HOH Details is a future feature.");
//ProcessArrivalDetails(_configuration);
}
else
ProcessArrivalSummary(_configuration);
UpdateLastRunDate(_configuration.ClientId, _configuration.LastRunDateId, DateTime.Now);
}
catch (Exception ex)
{
if (_configuration == null)
{
string[] messageTo = new[] { "aaaaaaaaaaaa#gmail.com" };
//string acctManagerEmail = Util.usp_GetEmailAcct(_clientId);
//string[] messageTo = new[] { "77777777777.com", acctManagerEmail };
EmailUtility.SendEmail(Util.EMAIL_FROM, messageTo,
"Error Running Report Utility for Client: " + _configuration.DbName, "Error Message: " + ex.Message,
Util.SMTP_SERVER, false);
}
throw new Exception("Error Occurred");
}
Here's my EmailUtility file:
namespace Common
{
public class EmailUtility
{
public static string SMTP_SERVER;
public static string[] GetEmailRecipientAdmin();
public static void SendEmail(string messageFrom, string[] messageTo, string messageSubject, string messageBody, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string[] messageTo, string[] messageCC, string messageSubject, string messageBody, string messageAttachmentPath, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string[] messageTo, string[] messageCC, string messageSubject, string messageBody, string[] messageAttachmentPath, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string messageTo, string messageSubject, string messageBody, string ipAddress, bool isHtml);
public static void SendEmail(string messageFrom, string messageTo, string messageSubject, string messageBody, string messageAttachmentPath, string ipAddress, bool isHtml);
}
}

Check if a C# string is a well formed url with a port number

I got a string which I check if it represents a URL like this:
if(Uri.IsWellFormedUriString(urlString, UriKind.Absolute)) ...
Is there also a way to add there a check if the url contains a port number?
You could offload all the heavy work to the Uri constructor:
var uri = new Uri(urlString);
Then you only need to interpret uri.Authority. If it contains a colon, the port is specified.
public static bool IncludesPort(this string urlAddress)
{
return new Uri(urlAddress).Authority.Contains(':');
}
public class StackoverflowQuestion
{
public string Run() {
string urlString = "http://mywebsite:8001/application/api";
if (Uri.IsWellFormedUriString(urlString, UriKind.Absolute) && urlString.IncludesPort())
return "The uri contains explicitly defined port";
return "";
}
}
public static class Extensions {
public static bool IncludesPort(this string urlAddress)
{
urlAddress = urlAddress.Replace("http://", "").Replace("https://", "");
var splitted = urlAddress.Split(':');
var port = splitted?[1].Split("/")?[0];
return port != null && int.TryParse(port, out _);
}
}

c# Send image from WPF to WebAPI

I have a WebAPI 2.1 service (ASP.Net MVC 4) that receive and image and related data.
I need to send this image from WPF application, but I get 404 not found error.
Server side
[HttpPost]
[Route("api/StoreImage")]
public string StoreImage(string id, string tr, string image)
{
// Store image on server...
return "OK";
}
Client side
public bool SendData(decimal id, int time, byte[] image)
{
string url = "http://localhost:12345/api/StoreImage";
var wc = new WebClient();
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var parameters = new NameValueCollection()
{
{ "id", id.ToString() },
{ "tr", time.ToString() },
{ "image", Convert.ToBase64String(image) }
};
var res=wc.UploadValues(url, "POST", parameters);
return true;
}
The url exists, I thing I need to encode to json format, but I don't know how.
Thanks for your time!
The method parameters in your case are received in QueryString form.
I would suggest you turn the parameters list into one single object like this:
public class PhotoUploadRequest
{
public string id;
public string tr;
public string image;
}
Then in you API convert the string to buffer from Base64String like this:
var buffer = Convert.FromBase64String(request.image);
Then cast it to HttpPostedFileBase
HttpPostedFileBase objFile = (HttpPostedFileBase)new MemoryPostedFile(buffer);
Now you have the image file. Do whatever you want.
Full Code here:
[HttpPost]
[Route("api/StoreImage")]
public string StoreImage(PhotoUploadRequest request)
{
var buffer = Convert.FromBase64String(request.image);
HttpPostedFileBase objFile = (HttpPostedFileBase)new MemoryPostedFile(buffer);
//Do whatever you want with filename and its binaray data.
try
{
if (objFile != null && objFile.ContentLength > 0)
{
string path = "Set your desired path and file name";
objFile.SaveAs(path);
//Don't Forget to save path to DB
}
}
catch (Exception ex)
{
//HANDLE EXCEPTION
}
return "OK";
}
Edit:
I forgot to add the Code for MemoryPostedFile class
public class MemoryPostedFile : HttpPostedFileBase
{
private readonly byte[] fileBytes;
public MemoryPostedFile(byte[] fileBytes, string fileName = null)
{
this.fileBytes = fileBytes;
this.FileName = fileName;
this.InputStream = new MemoryStream(fileBytes);
}
public override void SaveAs(string filename)
{
File.WriteAllBytes(filename, fileBytes);
}
public override string ContentType => base.ContentType;
public override int ContentLength => fileBytes.Length;
public override string FileName { get; }
public override Stream InputStream { get; }
}

how to remove duplication from this c# code block

I wrote this code but during code review process it was suggested that this is duplicate code and I need to remove code duplication from this code. Can anyone suggest how I can make this code better to avoid duplication.
private void ShowHideEmailContents(string email, string email2, string format, string tooltip, bool isReadOnly)
{
if (isReadOnly)
{
hlEmail.NavigateUrl = string.Format(format, email);
hlEmail2.NavigateUrl = string.Format(format, email2);
hlEmail.Text = email;
hlEmail2.Text = email2;
hlEmail.ToolTip = tooltip;
hlEmail2.ToolTip = tooltip;
hlEmail.Visible = isReadOnly;
hlEmail2.Visible = isReadOnly;
txtEmail.Visible = !isReadOnly;
txtEmail2.Visible = !isReadOnly;
}
else
{
txtEmail.Text = email;
txtEmail2.Text = email2;
}
}
Note that the duplication exists because you do the same things twice, just on different objects.
To fix that, create a new method which does those things only once:
private static void ShowHideEmailContents(?? hl, ?? txt, string email, string format, string tooltip, bool isReadOnly)
{
if (isReadOnly)
{
hl.NavigateUrl = string.Format(format, email);
hl.Text = email;
...
}
else
{
txt.Text = email;
}
}
and call it twice:
private void ShowHideEmailContents(string email, string email2, string format, string tooltip, bool isReadOnly)
{
ShowHideEmailContents(hlEmail, txtEmail, email, format, tooltip, isReadOnly);
ShowHideEmailContents(hlEmail2, txtEmail2, email2, format, tooltip, isReadOnly);
}
You can minimise the number of parameters that you pass by encapsulating the logic to set the email object's properties in a class:
public sealed class EmailOptionsSetter
{
readonly string _tooltip;
readonly string _format;
readonly bool _isReadOnly;
public EmailOptionsSetter(string tooltip, string format, bool isReadOnly)
{
_tooltip = tooltip;
_format = format;
_isReadOnly = isReadOnly;
}
public void SetOptions(YourEmailType emailObj, string email)
{
emailObj.NavigateUrl = string.Format(_format, email);
emailObj.Text = email;
emailObj.ToolTip = _tooltip;
emailObj.Visible = _isReadOnly;
}
}
Then you can call it like this:
private void ShowHideEmailContents(string email, string email2, string format, string tooltip, bool isReadOnly)
{
if (isReadOnly)
{
var optionsSetter = new EmailOptionsSetter(tooltip, format, isReadOnly);
optionsSetter.SetOptions(hlEmail, email);
optionsSetter.SetOptions(hlEmail2, email2);
txtEmail.Visible = !isReadOnly;
txtEmail2.Visible = !isReadOnly;
}
else
{
txtEmail.Text = email;
txtEmail2.Text = email2;
}
}

MSMQ custom message format

I would like to make message in MSMQ which will have text for example
<order><data id="5" color="blue"/></order>
This is standard XML. So far I have made Serializable class
[Serializable]
public class order
string id
string color
I am using BinaryFormatter. When i check the message.BodyStream there are some chars which are not supposed to be there( 00,01,FF ), then I cannot receive this message without error.
This task seems to be simple, just put text
<order><data id="5" color="blue"/></order>
into msmq.
Mine whole important code:
public static void Send()
{
using (message = new Message())
{
request req = new request("1", "blue");
message.Recoverable = true;
message.Body = req.ToString();
message.Formatter = new BinaryMessageFormatter();
using (msmq = new MessageQueue(#".\Private$\testrfid"))
{
msmq.Formatter = new BinaryMessageFormatter();
msmq.Send(message, MessageQueueTransactionType.None);
}
}
}
[Serializable]
public class request
{
private readonly string _order;
private readonly string _color;
public request(string order, string color)
{
_order = order;
_color = color;
}
public request()
{ }
public string Order
{
get { return _order; }
}
public string Color
{
get { return _color; }
}
public override string ToString()
{
return string.Format(#"<request> <job order = ""{0}"" color = ""{1}"" /> </request>",_order,_color);
}
}
Your question isn't very clear at all; you can send any type of message you like to MSMQ, so long as you use the BinaryMessageFormatter. Here's an example:
string error = "Some error message I want to log";
using (MessageQueue MQ = new MessageQueue(#".\Private$\Your.Queue.Name"))
{
BinaryMessageFormatter formatter = new BinaryMessageFormatter();
System.Messaging.Message mqMessage = new System.Messaging.Message(error, formatter);
MQ.Send(mqMessage, MessageQueueTransactionType.Single);
MQ.Close();
}
I have not found reason why the Message.Body contains these ascii characters before the string I pass to Body. I just fill directly BodyStream instead of Body and let it convert itself:
Message.BodyStream = new MemoryStream(Encoding.ASCII.GetBytes(string i want to put as Body))
Then the message is simply only the string with nothing else.
You don't need the serializable class to send a string to a message queue.
Since you are using the BinaryMessageFormatter, you must first convert your string to a byte array using a text encoder e.g.
message.Body = new UTF8Encoding().GetBytes(req.ToString());
I'm just using UTF8 as an example, you can use whatever encoding you like.
Then when you read the message from the queue, remember to use the same encoding to get your string back e.g.
string myString = new UTF8Encoding().GetString(message.Body);
Hope this helps

Categories