Mail Attachment and its Content Transfer Encoding setting (BlackBerry problem) - c#

I use a C# code to send some e-mails to different users with mail clients on different platforms: BlackBerry, iPhone, Pc, Mac, etc. Here is the snippet:
Attachment attachment = null;
if (attachNameFile!=null)
{
attachment = new Attachment(attachNameFile, new System.Net.Mime.ContentType(attachMimeType));
}
SmtpClient smtp = new SmtpClient
{
Host = this.smtpServer,
Port = this.smtpPort,
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential()
};
using (MailMessage message = new MailMessage())
{
message.From = fromAddress;
if (macTo != null) message.To.AddRangeUnique(macTo);
if (macCc!=null) message.CC.AddRangeUnique(macCc);
if (macCcn != null) message.Bcc.AddRangeUnique(macCcn);
message.Subject = subject;
message.Body = sb.ToString();
if (replyTo != null)
message.ReplyTo = new MailAddress(replyTo);
else
message.ReplyTo = fromAddress;
if (attachment!=null)
{
message.Attachments.Add(attachment);
}
smtp.Send(message);
}
Some user told me that the message he or she receives doesn't have the attachment. The attachment is a text (UTF8) file.
After some analysis, I saw that the attachment is shown in the body of the mail and only some mail clients show it as an attachment. It is not a problem for me, but BlackBerry has some problem with this kind of attachments, because it shows only the body and cut off the attachment. But it works in Google, iMail, Thunderbird, etc. etc.
I analysed the source of the message and I saw the ContentTransferEncoding of the attacchment is 8 bit:
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; name=Attachment.2324333.txt
I think I resolve my problem if I set the ContentTransferEncoding property of the object Attachment in C# to Base64 encoding:
Attachment attachment = null;
if (attachNameFile!=null)
{
attachment = new Attachment(attachNameFile, new System.Net.Mime.ContentType(attachMimeType));
attachment.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
}
Do you think it is a good and working approach? Do I have to set other properties?
Thanks to all

Looking at some of the attachments coming from my BlackBerry, I think you need to add a Content-Disposition header:
Content-Transfer-Encoding: base64
Content-Type: text/plain
Content-Disposition: attachment; filename="myfilename.bin"

See: Sending email with attachments from C#, attachments arrive as Part 1.2 in Thunderbird
Content Disposition was the solution for my problem.

Seems to me you're doing everything right, the other mail clients prove it. Try BASE64, there's a good chance BlackBerry will like it, but you can't be sure until you actually see it :).

Related

How to send MIME email with attachments from Graph SDK? Preventing Graph API from Creating winmail.dat attachment

I'm using graph sdk from c# to send emails from a web app. The body is formatted as HTML. I'm attaching PDFs to the email. The recipients are receiving the email with winmail.dat and sometimes noname. It seems like the email is coming in as plain text. Gmail seems to able to unpack winmail.dat, but not all clients seem to do this.
Some research tells me to use MIME format, but having trouble finding a concise example.
How can I send emails from graph api / sdk formatted as HTML with MIME with attachments without creating winmail.dat
Here's a snip from my create message code:
private MimeMessage GetMimeMessage(string fromEmail, string subject, string htmlBody, IEnumerable<string> toRecipients, IEnumerable<string> ccRecipients, IEnumerable<string> attachments)
{
var message = new MimeMessage();
foreach (var recipient in toRecipients)
message.To.Add(MailboxAddress.Parse(recipient));
foreach (var recipient in ccRecipients)
message.Cc.Add(MailboxAddress.Parse(recipient));
message.From.Add(MailboxAddress.Parse(fromEmail));
message.Subject = subject;
var builder = new BodyBuilder();
builder.TextBody = htmlBody;
builder.HtmlBody = htmlBody;
foreach (var attachment in attachments)
builder.Attachments.Add(attachment);
message.Body = builder.ToMessageBody();
return message;
}
Send Code:
private async Task SendMimeMessageWithGraph(string sendFromEmail, MimeMessage mimeMessage)
{
var stream = new MemoryStream();
mimeMessage.WriteTo(stream);
stream.Position = 0;
StringContent MessagePost = new StringContent(Convert.ToBase64String(stream.ToArray()), Encoding.UTF8, "text/plain");
var message = new Message();
var mypost = await MessagePost.ReadAsStringAsync();
var sendMailRequest = _GraphClient.Users[sendFromEmail].SendMail(message, true).Request().GetHttpRequestMessage();
sendMailRequest.Content = MessagePost;
sendMailRequest.Method = HttpMethod.Post;
var sendResult = await _GraphClient.HttpProvider.SendAsync(sendMailRequest);
Debug.WriteLine(sendResult.StatusCode);
}
From: fromemail#fromemail.com
Date: Tue, 06 Sep 2022 21:39:47 -0400
Subject: Invoice #0000003
Message-Id: <2FWZXJIFTHU4.JPGM32IG50SI2#person1234>
To: Newperson#new.com
Cc: cc#cc.cc
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="=-9G8gCZS3S+XQhQ+1kLqUog=="
--=-9G8gCZS3S+XQhQ+1kLqUog==
Content-Type: text/plain; charset=utf-8
Please see attached invoice.<br><br>Thank you for your business,<br>Test<br>Person<br>222-999-1111<br>email#email.com<br><img height="50px" width="auto" src="data:image/svg+xml;base64,PD94b...>">
--=-9G8gCZS3S+XQhQ+1kLqUog==
Content-Type: text/html; charset=utf-8
Please see attached invoice.<br><br>Thank you for your business,<br>Test<br>Person<br>222-999-1111<br>email#email.com<br><img height="50px" width="auto" src="data:image/svg+xml;base64,PD94...">
--=-9G8gCZS3S+XQhQ+1kLqUog==--
I've followed this blog post:
https://gsexdev.blogspot.com/2021/08/sending-mimemessage-via-microsoft-graph.html
It partially works; emails received by clients without o365/outlook do not render the html email and include winmail.dat attachment. So, I still have the same issue.
In my case, I needed to disable TNEF formatting by disabling RTF. This is done through the online Exchange Admin Center:
Mail Flow
Remote domains
Choose 'Default'(or whatever you have set)
Edit text and character set
List item
Use rich-text format: Never.
Save.
Now both Graph SDK Messages and MIME messages send emails via graph as expected!

How to use razor engine for email templating with image src

I've found this link on how to using Razor Engine for email templates in asp.net and it worked great. But I've tried to have a logo in the email template with an image.
Something like this:
EmailTemplate.cshtml (this by the way is a strongly-type view)
<html>
<body>
<img src="logo.jpg" />
</body>
</html>
and when I try to submit it on email, it seems that the image path was not read, it only rendered an X in the content.
I'm thinking to pass the image path as part of the Model but it seems odd that way. Is there any way to achieve this?
Any help would be much appreciated. Thanks
To see image everywhere you can use these options:
Absolute Url
You can simply use full absolute path of image for example "http://example.com/images/logo.png"
IMO It is the most simple option and recommended for your problem.
Attachment
As mentioned by Mason in comments You can attach image to mail and then put image tag and useContentId of attachment:
//(Thanks to Mason for comment and Thanks to Bartosz Kosarzyck for sample code)
string subject = "Subject";
string body = #"<img src=""$CONTENTID$""/> <br/> Some Content";
MailMessage mail = new MailMessage();
mail.From = new MailAddress("from#example.com");
mail.To.Add(new MailAddress("to#example.com"));
mail.Subject = subject;
mail.Body = body;
mail.Priority = MailPriority.Normal;
string contentID = Guid.NewGuid().ToString().Replace("-", "");
body = body.Replace("$CONTENTID$", "cid:" + contentID);
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
//path of image or stream
LinkedResource imagelink = new LinkedResource(#"C:\Users\R.Aghaei\Desktop\outlook.png", "image/png");
imagelink.ContentId = contentID;
imagelink.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
htmlView.LinkedResources.Add(imagelink);
mail.AlternateViews.Add(htmlView);
SmtpClient client = new SmtpClient();
client.Host = "mail.example.com";
client.Credentials = new NetworkCredential("from#example.com", "password");
client.Send(mail);
Data Uri
you can use data uri (data:image/png;base64,....).
Not Recommended because of weak support in most of mail clients, I tested it with Outlook.com(web) and OutlookWebAccess(web) and Office Outlook(Windows) and Outlook(windows 8.1) and unfortunately it worked only on OutlookWebAccess(web).

Get file to send as attachment from byte array

I have an ASP.NET MVC application that has to send an email to a list of recipients with an attachment detailing a specific "Project". I get the details for this from a report by making use of SQL Server Reporting Services (SSRS).
I've never really used SSRS before, but I received some code from a colleague where he used it. What he does with the report is he downloads it in the browser to the client's machine. So, if I don't do that I sit with a byte array containing the report data.
Is there a way I can send this as an attachment without first physically writing the file to the filesystem of the server? The report will either be in excel format or a pdf.
Edit: I am using SmtpClient to send the email's.
Get the file data in a byte[]
byte[] binaryFile = // get your file data from the SSRS ...
string filename = "SSRS.pdf";
Prepare a list or array of the destination addresses:
string[] addresses = // get addresses somehow (db/hardcoded/config/...)
sending smtp message through SmtpClient:
MailMessage mailMessage= new MailMessage();
mailMessage.From = new MailAddress("sender email address goes here");
// Loop all your clients addresses
foreach (string address in addresses)
{
mailMessage.To.Add(address);
}
mailMessage.Subject = "your message subject goes here";
mailMessage.Body = "your message body goes here";
MemoryStream memoryStream = new MemoryStream(binaryFile);
mailMessage.Attachments.Add( new Attachment( memoryStream, filename , MediaTypeNames.Application.Pdf ));
SmtpClient smtpClient = new SmtpClient();
smtpClient.Send(mailMessage);
to do this you would need to leverage off the SSRS ReportManager API as follows.
First read in the report from the Web Service with SSRS
Read the file into memory rather than saving to the server or client
Send the MemoryStream object straight to the email server.
Reporting services: Get the PDF of a generated report
How to send an email with attachments using SmtpClient.SendAsync?
string strReportUser = "RSUserName";
string strReportUserPW = "MySecretPassword";
string strReportUserDomain = "DomainName";
string sTargetURL = "http://SqlServer/ReportServer?" +
"/MyReportFolder/Report1&rs:Command=Render&rs:format=PDF&ReportParam=" +
ParamValue;
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create( sTargetURL );
req.PreAuthenticate = true;
req.Credentials = new System.Net.NetworkCredential(
strReportUser,
strReportUserPW,
strReportUserDomain );
HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse();
Stream fStream = HttpWResp.GetResponseStream();
HttpWResp.Close();
//Now turn around and send this as the response..
ReadFullyAndSend( fStream );
ReadFullyAnd send method.
NB: the SendAsync call so your not waiting for the server to send the email completely before you are brining the user back out of the land of nod.
public static void ReadFullyAndSend( Stream input )
{
using ( MemoryStream ms = new MemoryStream() )
{
input.CopyTo( ms );
MailMessage message = new MailMessage("from#foo.com", "too#foo.com");
Attachment attachment = new Attachment(ms, "my attachment",, "application/vnd.ms-excel");
message.Attachments.Add(attachment);
message.Body = "This is an async test.";
SmtpClient smtp = new SmtpClient("localhost");
smtp.Credentials = new NetworkCredential("foo", "bar");
smtp.SendAsync(message, null);
}
}

Best way for sending advance email

I'd like to send email by asp.net . I use this code and it is work fine.
mail.From = new MailAddress("mail#gmail.com", "sender", System.Text.Encoding.UTF8);
string to = Session["Umail"].ToString();
mail.To.Add(to);
mail.IsBodyHtml = true;
mail.SubjectEncoding = Encoding.UTF8;
mail.BodyEncoding = Encoding.GetEncoding("utf-8");
mail.Subject = "subject";
mail.Body = "body" ;
SmtpClient smtp = new SmtpClient("Smtp.gmail.Com", 587);
smtp.UseDefaultCredentials = false;
smtp.EnableSsl = true;
smtp.Credentials = new NetworkCredential("mail#gmail.com", "pass"); smtp.Send(mail);
But I'd like a custom and beautiful mail. Like emails that send from facebook, google team and etc. I know that can use html tag in mail.Body but is it good way? What is the best way ?
This is ready to use code snippet which I use for sending email which contains both text content and the content based on a html template:
// first we create a plain text version and set it to the AlternateView
// then we create the HTML version
MailMessage msg = new MailMessage();
msg.From = new MailAddress("from#email", "From Name");
msg.Subject = "Subject";
msg.To.Add("to#email");
msg.BodyEncoding = Encoding.UTF8;
String plainBody = "Body of plain email";
//first we create the text version
AlternateView plainView = AlternateView.CreateAlternateViewFromString(plainBody, Encoding.UTF8, "text/plain");
msg.AlternateViews.Add(plainView);
//now create the HTML version
MailDefinition message = new MailDefinition();
message.BodyFileName = "~/MailTemplates/template1.htm";
message.IsBodyHtml = true;
message.From = "from#email";
message.Subject = "Subject";
//Build replacement collection to replace fields in template1.htm file
ListDictionary replacements = new ListDictionary();
replacements.Add("<%USERNAME%>", "ToUsername");//example of dynamic content for Username
//now create mail message using the mail definition object
//the CreateMailMessage object takes a source control object as the last parameter,
//if the object you are working with is webcontrol then you can just pass "this",
//otherwise create a dummy control as below.
MailMessage msgHtml = message.CreateMailMessage("to#email", replacements, new LiteralControl());
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(msgHtml.Body, Encoding.UTF8, "text/html");
//example of a linked image
LinkedResource imgRes = new LinkedResource(Server.MapPath("~/MailTemplates/images/imgA.jpg"), System.Net.Mime.MediaTypeNames.Image.Jpeg);
imgRes.ContentId = "imgA";
imgRes.ContentType.Name = "imgA.jpg";
imgRes.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
htmlView.LinkedResources.Add(imgRes);
msg.AlternateViews.Add(htmlView);
//sending prepared email
SmtpClient smtp = new SmtpClient();//It reads the SMPT params from Web.config
smtp.Send(msg);
and these are key parts of the html template:
<p>Username: <%USERNAME%></p>
<img src="cid:imgA"/>
I'd like a custom and beautiful mail.
I know that can use html tag in mail.Body but is it good way? What is
the best way ?
I don't know exactly what is that supposed to mean, but generally, there are two ways to do it. (If we talking about images or sources in email etc..)
You can use LinkedResource class of .NET Framework.
Represents an embedded external resource in an email attachment, such
as an image in an HTML attachment.
Alternatively, and more simply in my opinion, if you want to use some images in your email, put the image in a public location then just reference that location in the HTML of the email.

How to send multi-part MIME messages in c#?

I want to send multi-part MIME messages with an HTML component plus a plain text component for people whose email clients can't handle HTML. The System.Net.Mail.MailMessage class doesn't appear to support this. How do you do it?
D'oh, this is really simple... but I'll leave the answer here for anyone who, like me, came looking on SO for the answer before Googling... :)
Credit to this article.
Use AlternateViews, like so:
//create the mail message
var mail = new MailMessage();
//set the addresses
mail.From = new MailAddress("me#mycompany.com");
mail.To.Add("you#yourcompany.com");
//set the content
mail.Subject = "This is an email";
//first we create the Plain Text part
var plainView = AlternateView.CreateAlternateViewFromString("This is my plain text content, viewable by those clients that don't support html", null, "text/plain");
//then we create the Html part
var htmlView = AlternateView.CreateAlternateViewFromString("<b>this is bold text, and viewable by those mail clients that support html</b>", null, "text/html");
mail.AlternateViews.Add(plainView);
mail.AlternateViews.Add(htmlView);
//send the message
var smtp = new SmtpClient("127.0.0.1"); //specify the mail server address
smtp.Send(mail);

Categories

Resources