0

At a high level, I'm trying to generate an outlook email item server side, and then return it to the client so that it opens in their local Outlook allowing them to make any changes they want(this as apposed to sending the email through SMTP).

This is really my first time ever working with file streams, and I'm not exactly sure how to proceed. I have the pretty basic start of what I'm trying to do, which is initially just get Outlook to open after this controller action returns the mail item. This code is what is called in the Controller to create the mail item. I don't have any of the logic for adding the various email addresses, body, subject etc as that isn't really relevant. Also this code gets called by the controller action, just placing it here in case I'm also doing something wrong creating the mail item.

     public MailItem CreateEmail(int id)
    {
        Application app = new Application();
        MailItem email = (MailItem)app.CreateItem(OlItemType.olMailItem);
        email.Recipients.Add("example@example.com");
        return email;
    }

Here is the controller action I would like to return this MailItem to the client. (This is what get's called via AJAX)

    public ActionResult GenerateEmail(int id)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            BinaryFormatter format = new BinaryFormatter();
            format.Serialize(ms, logic.CreateEmail(id));
            return File(ms, "message/rfc822");
        }
    }

The code breaks at format.Serialize giving me the error that my _COM object isn't able to be serialized. Is there a way to do what I am trying to do, or should I look for other methods to achieve this goal instead?

Richard Cawthon
  • 421
  • 5
  • 20

2 Answers2

0

Firstly, Outlook Object Model cannot be used in a service (such as IIS). Secondly, since you are only specifying the recipient address, why not use the mailto link on the client side?

If you still want to send the message, you can generate an EML (MIME) file - Outlook should be able to open it just fine. To make it look unsent, use the X-Unsent MIME header.

Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
  • Thanks Dmitry . Like I said above I am adding more than just the recipient, there will be a specific body generated dependent on options the user selects. The To, CC, and BCC fields will all be dynamic as well depending on user selection. Since the question isn't about that, I removed the logic to make it a little easier to read. Is there a possibility you could post a code example of what you explained above? Trying to research EML (MIME) file creation as I type this. – Richard Cawthon Aug 27 '15 at 18:17
  • EML is just a simple text file, you probably won't even need any libraries to create one. – Dmitry Streblechenko Aug 27 '15 at 18:18
0

Based largely on code from here,

public ActionResult DownloadEmail()
{
    var message = new MailMessage();

    message.From = new MailAddress("from@example.com");
    message.To.Add("someone@example.com");
    message.Subject = "This is the subject";
    message.Body = "This is the body";

    using (var client = new SmtpClient())
    {
        var id = Guid.NewGuid();

        var tempFolder = Path.Combine(Path.GetTempPath(), Assembly.GetExecutingAssembly().GetName().Name);

        tempFolder = Path.Combine(tempFolder, "MailMessageToEMLTemp");

        // create a temp folder to hold just this .eml file so that we can find it easily.
        tempFolder = Path.Combine(tempFolder, id.ToString());

        if (!Directory.Exists(tempFolder))
        {
            Directory.CreateDirectory(tempFolder);
        }

        client.UseDefaultCredentials = true;
        client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
        client.PickupDirectoryLocation = tempFolder;
        client.Send(message);

        // tempFolder should contain 1 eml file

        var filePath = Directory.GetFiles(tempFolder).Single();

        // stream out the contents - don't need to dispose because File() does it for you
        var fs = new FileStream(filePath, FileMode.Open);
        return File(fs, "application/vnd.ms-outlook", "email.eml");
    }
}

This works fine in Chrome but IE doesn't want to open it, maybe it has some extra security features. Try fiddling around with the content type and file extension and you might be able to get it to work in both.

Community
  • 1
  • 1
Paul Abbott
  • 7,065
  • 3
  • 27
  • 45
  • The one thing I had to add to this was `message.Headers.Add("X-Unsent", "1");` as Dmitry suggested so the message would open in composition mode. It also opened in IE for me without any changes, so I assume it might be specific versions of IE that are the problem? Honestly I'm not COMPLETELY positive about what the code is doing but it works. :) – Richard Cawthon Aug 27 '15 at 21:27