In my program, I am reading an Exchange mailbox using EWS .NET API and forwarding the emails as attachment to an external email address. Code that I have used is below
private void ForwardMessage(ExchangeService exchangeService, EmailMessage item)
{
ResponseMessage responseMessage = item.CreateForward();
item.Load(new PropertySet(BasePropertySet.FirstClassProperties, new
PropertySet(){ItemSchema.MimeContent,
ItemSchema.Subject}));
var mail = new EmailMessage(exchangeService);
var attachment = mail.Attachments.AddFileAttachment(String.Format("
{0}.eml", item.Subject),
item.MimeContent.Content);
String forwardEmailAddresses =
MailProcessorSettings.Default.ForwardEmailAddress;
char[] delimiters = { ',', ';' };
foreach (var emailAddress in forwardEmailAddresses.Split(delimiters,
StringSplitOptions.RemoveEmptyEntries))
{
mail.ToRecipients.Add(emailAddress);
}
mail.Subject = item.Subject;
mail.Send();
}
I am able to open the email forwarded as attachment in Outlook. However, if I send it to Gmail or to other users using different email clients it shows up as a blank attachment.
How do I ensure that the email forwarded as an attachment preserves the original content?
Adding a line indicating the content type of the message seems to fix this issue. Either of the following settings seems to work. After adding the ContentType, I was able to download the attachment from Gmail although I had to use the Outlook Client to open it.
attachment.ContentType = "multipart/alternative"
OR
attachment.ContentType = "message/rfc822"
Related
In an ASP/C# application I'm sending an email with 3 file attached. The 3 files are the same type, same extension and more or less same size ( but none are empty ).
The email is sent correctly. If I open it using outlook, I have no problems. I can see the body, and the 3 files attached.
But here is my issue: If I send that mail to a Gmail Adress, then on Gmail I can see only 2 attachments.
And if I click on the download all attachment icon ( on the right ), it will download the 2 visible attachment + the third one but empty.
It's a really weird issue.
Also there is a 4th attachment which is an embedded image. And this image is display correctly in the mail body.
Here is the code I'm using to send the mail:
MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient("SMTP_IP_ADRESS", SMTP_IP_PORT);
mail.From = new MailAddress("MYEMAIL#DOMAIN.COM");
mail.To.Add("GMAIL_EMAIL");
mail.To.Add("OUTLOOK_EMAIL");
mail.Subject = "MSN "+Request.Params["nameMsn"];
Attachment imageAttachment = new
Attachment(Server.MapPath(Url.Content("~/Content/images/image.png")));
string contentID = "logoCare";
imageAttachment.ContentId = contentID;
mail.IsBodyHtml = true;
mail.Body = "<html><body>Have a good day.<br/>Best regards. <br/><br/><img width='200'
src=\"cid:"
+ contentID + "\"></body></html>";
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i];
var attachment = new Attachment(file.InputStream, file.FileName,
MediaTypeNames.Application.Octet);
mail.Attachments.Add(attachment);
}
mail.Attachments.Add(imageAttachment);
SmtpServer.Send(mail);
The third attachment you see empty can possibly be the CID embedded image that web based email clients (like Gmail) can't manage, meanwhile it works with desktop email clients like Outlook. Can you verify this?
Please take a look at here
I am using Mimekit to receive mail from Gmail using C# for IOT notifications, which seems to be working.
I would like to do the following:
Log in to Gmail
Search inbox mail containing a specific keyword in subject or body.
Parse the body like you would a text file in C#
Download a attachment (test.txt)
Delete
At this point I am able to login successfully and retrieve a list of folders and matches for a string.
Here is my code:
using (var client = new ImapClient())
{
client.Connect("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
// disable OAuth2 authentication unless you are actually using an access_token
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate("user#gmail.com", "password");
MessageBox.Show("we're connected");
// The Inbox folder is always available on all IMAP servers...
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
//1. search for all messages containing the string test123
var query = SearchQuery.FromContains("test123");
foreach (var uid in inbox.Search(query))
{
var message = inbox.GetMessage(uid);
System.Diagnostics.Debug.WriteLine("[match] {0}: {1}", uid, message.Subject);
//2. Show all folders in Personal
var personal = client.GetFolder(client.PersonalNamespaces[0]);
foreach (var folder in personal.GetSubfolders(false))
System.Diagnostics.Debug.WriteLine("[folder] {0}", folder.Name);
}
client.Disconnect(true);
MessageBox.Show("disconnected ");
}
So my question is: How do I accomplish steps 3 , 4 and 5?
using (var client = new ImapClient ()) {
client.Connect ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
// disable OAuth2 authentication unless you are actually using an access_token
client.AuthenticationMechanisms.Remove ("XOAUTH2");
// 1. Log in to Gmail
client.Authenticate ("user#gmail.com", "password");
// 2. Search inbox mail containing a specific keyword in subject or body.
client.Inbox.Open (FolderAccess.ReadWrite);
var query = SearchQuery.SubjectContains ("123").Or (SearchQuery.BodyContains ("123"));
foreach (var uid in client.Inbox.Search (query)) {
// 3. Parse the body like you would a text file in C#
// This downloads and parses the full message:
var message = client.Inbox.GetMessage (uid);
// 4. Download a attachment (test.txt)
// No need to download an attachment because you already
// downloaded it with GetMessage().
// Here's how you could get the "test.txt" attachment:
var attachment = message.BodyParts.OfType<MimePart> ()
.FirstOrDefault (x => x.FileName == "test.txt");
// 5. Delete
// This marks the message as deleted, but does not purge it
// from the folder.
client.Inbox.AddFlags (uid, MessageFlags.Deleted, true);
}
// Purge the deleted messages (if you use Thunderbird, this is aka "Compact Folders")
client.Inbox.Expunge ();
client.Disconnect (true);
}
I'm wondering how to send meeting request to allow GMail correctly recognize it?
If you try to send iCalendar meeting request definition given bellow as an alternative view using habitual code (also given bellow) via MailMessage object to GMail it will be resulted in not recognized meeting request:
But the mail with exactly the same meeting request sent via GMail UI results in recognized meeting request! Puzzling.
Does anybody know what "magic" I'm missing?
Good to notice that Outlook correctly recognizes exactly the same meeting request sent by given code.
The code to send mail with meeting request:
class Program
{
static string From = "sender#example.com";
static string TimeFormat = "yyyyMMdd\\THHmmss\\Z";
static string To = "target#example.dom";
static void Main(string[] args)
{
string content = ReadFile("event-template.ics");
content = content.Replace("#TO#", To);
content = content.Replace("#FROM#", From);
content = content.Replace("#UID#", Guid.NewGuid().ToString().Replace("-", ""));
content = content.Replace("#CREATED-AT#", DateTime.UtcNow.AddDays(-1).ToString(TimeFormat));
content = content.Replace("#DTSTART#", DateTime.UtcNow.AddDays(1).ToString(TimeFormat));
content = content.Replace("#DTEND#", DateTime.UtcNow.AddDays(1).AddHours(1).ToString(TimeFormat));
MailMessage message = new MailMessage();
message.From = new MailAddress(From);
message.To.Add(new MailAddress(To));
message.Subject = "Meeting Request from Code!";
var iCalendarContentType = new ContentType("text/calendar; method=REQUEST");
var calendarView = AlternateView.CreateAlternateViewFromString(content, iCalendarContentType);
calendarView.TransferEncoding = TransferEncoding.SevenBit;
message.AlternateViews.Add(calendarView);
using (var smtp = new SmtpClient())
{
smtp.Send(message);
}
}
public static string ReadFile(string fileName)
{
using (StreamReader r = new StreamReader(fileName))
{
return r.ReadToEnd();
}
}
}
iCalendar template definition:
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//A//B//EN
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
ORGANIZER;CN="Organizer":mailto:#FROM#
ATTENDEE;CN="Attendee";CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=
NEEDS-ACTION;RSVP=TRUE:mailto:#TO#
DTSTART:#DTSTART#
DTEND:#DTEND#
LOCATION:Location test
TRANSP:OPAQUE
SEQUENCE:0
UID:#UID#
DTSTAMP:#CREATED-AT#
CREATED:#CREATED-AT#
LAST-MODIFIED:#CREATED-AT#
DESCRIPTION:Test description\n
PRIORITY:5
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR
UPD. The source of email generated by code and received by GMail (not recognized by GMail as a meeting request): http://pastebin.com/MCU6P16Y.
The source of email composed by GMail during forwarding (recognized correclty): http://pastebin.com/zfbbj9Gg
IMPORTANT UPDATE. Just changing target from my email (<my>#gmail.com) to my colleague's one (<colleague>#gmail.com) and it starts to recognize properly! Now it definitely looks like GMail issue.
(I'm sending email from the address that differs from target, sure)
UPDATE. Found exactly the same issue in GMail support forum: Bug: Gmail fails to recognize .ics calendar invitations attached to incoming messages. The issue dated by Jun, 2011 and reported as fixed to Jul, 2011. I've created new topic there: GMail fails to recognize *.ics attachment as a meeting request.
It seems that the problem is not with GMAIL recognizing the meeting request, but with problems displaying it. I was bugged by the same problem.
It was "fixed" after I changed GMAIL display language to "English (US)" from Settings menu.
So it is definitely a bug.
If you're using c# I managed to get this working outlook web, gmail, outlook 2016.
What it appears you need to do is add an alternate view, this doesn't appear to work when you have multiple views but does work for your example above.
The alternative view below:
var ct = new ContentType("text/calendar");
if (ct.Parameters != null)
{
ct.Parameters.Add("method", "REQUEST");
ct.Parameters.Add("charSet", "utf-8");
var avCal = AlternateView.CreateAlternateViewFromString(calendarAppt.ToString(), ct);
avCal.TransferEncoding = TransferEncoding.Base64;
mail.AlternateViews.Add(avCal);
}
I have a WCF service that sends email based on user input. It was brought to my attention that, recently, a particular user's email were being delivered without any body text. If .IsBodyHtml is set to true, no body text is transferred; but, if .IsBodyHtml is set to false, the body has the appropriate text. However, it doesn't seem to be consistent, as it seems to occur only when said user's email address is set as the "From" address.Tech Details:We have an MS Exchange mail server. I'm composing a MailMessage object passing it to the built-in SMTP class to send the message.
The code has been simplified, a bit, for brevity/clarity. Nevertheless, the original code is pretty standard/straight-forward. email refers to a LINQ-to-SQL class object
MailMessage message = new MailMessage();
message.From = new MailAddress(email.fromAddress);
message.To.Add(email.toRecipient);
message.Subject = email.emailSubject;
//set email body
message.IsBodyHtml = true;
message.Body = email.emailBody;
Attachment attachmentFile = null;
if (email.hasAttachment == true)
{
//retrieve attachments for emailID
var attachments = from attach in db.EmailAttachments
where attach.emailID == emailID
select attach;
foreach (var attachment in attachments)
{//attach each attachment
string filePath = Path.Combine(UPLOAD_DIRECTORY, emailID.ToString(), attachment.fileName);
attachmentFile = new Attachment(filePath);
message.Attachments.Add(attachmentFile); //set attachment from input path
}
}
SmtpClient client = new SmtpClient(SMTP_SERVER, SMTP_PORT); //set SMTP server name/URL and port
client.Send(message); //try to send the SMTP email
Since the problem relates to a user, it is probably related to the setting of this user.
Log in as that user and open outlook
Select: File -> Options -> Mail
Scroll down to the section "Message Format"
Probably "Convert to PlainText Format is selected" change this to "Convert to HTML Format"
I use this class to send mails trough a gmail account:
public class GmailAccount
{
public string Username;
public string Password;
public string DisplayName;
public string Address
{
get
{
return Username + "#gmail.com";
}
}
private SmtpClient client;
public GmailAccount(string username, string password, string displayName = null)
{
Username = username;
Password = password;
DisplayName = displayName;
client = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(Address, password)
};
}
public void SendMessage(string targetAddress, string subject, string body, params string[] files)
{
MailMessage message = new MailMessage(new MailAddress(Address, DisplayName), new MailAddress(targetAddress))
{
Subject = subject,
Body = body
};
foreach (string file in files)
{
Attachment attachment = new Attachment(file);
message.Attachments.Add(attachment);
}
client.Send(message);
}
}
Here is an example of how I use it:
GmailAccount acc = new GmailAccount("zippoxer", "******", "Moshe");
acc.SendMessage("zippoxer#gmail.com", "Hello Self!", "like in the title...", "C:\\822d14ah857.r");
The last parameter in the SendMessage method is the location of an attachment I want to add.
I tried sending a mail with an attachment of 400KB, worked great (even 900KB works). But then I tried uploading an attachment of 4MB, didn't work. Tried 22MB -> didn't work too.
There should be a limit of 25MB per message in Gmail. My message's subject and body are almost empty so don't consider them as part of the message's size. Why do I have that low limit?
According to this post, it is a bug in .Net 4.0. The limit specified in the post is 3,050,417 bytes. You can try the work-around code included in the post. Hope this helps.
http://connect.microsoft.com/VisualStudio/feedback/details/544562/cannot-send-e-mails-with-large-attachments-system-net-mail-smtpclient-system-net-mail-mailmessage
It's still possible to send. Just change the attachment encoding to something other than Base64. I tried testing this and found that there is a IndexOutOfBoundsException in the Base64 encoding code. I was able to successfully send an 11MB file to myself using TransferEncoding.SevenBit.
Check and see if the SmtpClient object is going out of scope or otherwise being disposed before the send is complete and has sent the QUIT to the server.
Okay, this is a bug in .net 4.
Microsoft says it will be fixed in the next service pack.