How to Save Mailmessage Object to Disk as *.Eml or *.Msg File

How to save MailMessage object to disk as *.eml or *.msg file

For simplicity, I'll just quote an explanation from a Connect item:

You can actually configure the
SmtpClient to send emails to the file
system instead of the network. You can
do this programmatically using the
following code:

SmtpClient client = new SmtpClient("mysmtphost");
client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
client.PickupDirectoryLocation = @"C:\somedirectory";
client.Send(message);

You can also set this up in your
application configuration file like
this:

 <configuration>
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="C:\somedirectory" />
</smtp>
</mailSettings>
</system.net>
</configuration>

After sending the email, you should
see email files get added to the
directory you specified. You can then
have a separate process send out the
email messages in batch mode.

You should be able to use the empty constructor instead of the one listed, as it won't be sending it anyway.

How to save MailMesage to .msg file?

How exactly are you creating the MSG file? It is completely different from an EML file - see https://stackoverflow.com/questions/16229591/difference-between-a-msg-file-and-a-eml-file/16230261#16230261

MSG file format is a binary IStorage file, and its format is documented. You can parse your EML (MIME) file and copy one property at a time to a programmatically created MSG file.

If using Redemption is an option (I am its author), you can use Session.CreateMessageFromMsgFile to create a new MSG file and RDOMail.Import method to import your existing EML file.

  set Session = CreateObject("Redemption.RDOSession")
set Msg = Session.CreateMessageFromMsgFile("c:\temp\test.msg")
Msg.Sent = true '//since Import does not copy this property
Msg.Import("c:\temp\test.eml", 1024) ' //1024 is olRfc822
Msg.Save

Save Email as .eml with original email.body

You are essentially reassembling the message from a few properties. Why not grab the whole MIME message (with all the headers, attachments etc.)?

See https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-export-items-by-using-ews-in-exchange

How to save System.Net.Mail MailMessage object into SQL Server database?

I think the update you posted is pretty good. Also check out this answer for How to save MailMessage object to disk as *.eml or *.msg file. You probably can create multiple clients, one to properly send and other to save the message to local file, which then needs to be saved to DB. I haven't tried this though.

If you are still looking into this, posted sample code...

Restricted to single attachment only. The sample is only to get you started and should not be taken as is. There is a lot of room for improvements.
We load the attachment into a byte[] and then add it as a Attachment(Stream s). We save this into the db as our VARBINARY content.

Your First send method, that also saves the message to db

try
{
MailMessage message = new MailMessage();
var logoPath = @"C:\MyLogo.jpg";
message.From = new MailAddress("from@email.co.nz");
message.To.Add("to@email.co.nz");
message.IsBodyHtml = true;

//Read the attachment into byte Array. This assumes single attachment only in the Mail Message.
byte[] arr = File.ReadAllBytes(logoPath);

using (var stream = new MemoryStream(arr))
{
stream.Position = 0;
Attachment logo = new Attachment(stream, "Logo");
string contentID = "Image";
logo.ContentId = contentID;
logo.ContentDisposition.Inline = true;
logo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;

string wsHdr = "<html><body><p><a href=\"http://www.tecnq.com.au\" target=\"_blank\"><img alt=\"tecnqlogo\" src=\"cid:" + contentID + "\" style=\"border-style:none; height:34px; width:100px\" /></a></p>" + "</html></body>"; ;

message.Body = wsHdr;
message.Attachments.Add(logo);


SmtpClient smtp = new SmtpClient();
smtp.Host = "MyServer";
smtp.Port = 25;
smtp.Send(message);
SaveMessage(message, arr);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

To Save the mail message

  //ZERO ERRO CHECKING.
private static void SaveMessage(MailMessage message, byte[] arr)
{
using (var conn = new SqlConnection("CONNECTION_STRING"))
{
using (var cmd = new SqlCommand("INSERT INTO MailSent (Body,Attachment) VALUES(@BODY,@ATTACHMENT)", conn))
{
conn.Open();
var param = new SqlParameter("@BODY", SqlDbType.VarChar)
{
Value = message.Body
};
var param2 = new SqlParameter("@ATTACHMENT", SqlDbType.Binary)
{
Value = arr
};
cmd.Parameters.Add(param);
cmd.Parameters.Add(param2);
cmd.ExecuteNonQuery();
}
}
}

Resend message

 try
{
MailMessage message = new MailMessage();
byte[] arr2 = null;
GetMailMessage(2, ref message, ref arr2);


message.From = new MailAddress("from@email.co.nz");
message.To.Add("to@email.co.nz");
message.IsBodyHtml = true;

using (var stream = new MemoryStream(arr2))
{
stream.Position = 0;
Attachment logo = new Attachment(stream, "Logo");
string contentID = "Image";
logo.ContentId = contentID;
logo.ContentDisposition.Inline = true;
logo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
message.Attachments.Add(logo);

SmtpClient smtp = new SmtpClient();
smtp.Host = "MyServer";
smtp.Port = 25;
smtp.Send(message);

}

// SaveMessage(message, arr);
}
catch (Exception ex)
{

Console.WriteLine(ex.ToString());
}

To Retrieve the message

    //ZERO ERROR CHECKING.
private static void GetMailMessage(int itemId, ref MailMessage msg2, ref byte[] arr2)
{
using (var conn = new SqlConnection("CONNECTION_STRING"))
{
using (var cmd = new SqlCommand("SELECT [Body],[Attachment] FROM MailSent WHERE ID = @itemId", conn))
{
conn.Open();
cmd.Parameters.AddWithValue("@itemId", itemId);

using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
msg2.Body = dr[0].ToString();
arr2 = dr[1] as byte[];
}
}
}
}
}

Create eml file in memory without saving it on disk

Look into using MimeKit.

You can write the MimeMessage objects to any type of stream that you want, including a MemoryStream.

Specify .eml file name using System.Net.Mail.MailAddress or other library

Allan Eagle over at CodeProject.com has created an extension of the System.Net.Mail.MailMessage class that includes the ability to save an email with a specific file name. I believe this will address the issue you raised.



Related Topics



Leave a reply



Submit