BDB
BDB

Reputation: 459

Saving email to the directory with specified file name is not working in .NET 5.0

I am trying to follow the approach suggested in a post by Allan Eagle in code-project. This same approach was working fine up until .NET Core 3.1, but not with .NET 5.0 . Here is the save method I created,

 private void Save(MailMessage message, string filePath)
    {
        var assembly = typeof(SmtpClient).Assembly;
        var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
        const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
        using (var fileStream = new FileStream(filePath, FileMode.Create))
        {
            var mailWriterContructor = mailWriterType.GetConstructors(bindingFlags)[0];
            var mailWriter = mailWriterContructor.Invoke(new object[] { fileStream });//<-- This line throws error saying parameter mismatch
            var sendMethod = typeof(MailMessage).GetMethod("Send", bindingFlags);
            sendMethod.Invoke(message, bindingFlags, null, new[] { mailWriter, true, true }, null);
            var closeMethod = mailWriter.GetType().GetMethod("Close", bindingFlags);
            closeMethod.Invoke(mailWriter, bindingFlags, null, new object[] { }, null);
        }
    }

I checked all the available underlying invoke methods and tried working with them passing needed parameters but non of them worked for me.

Error Message: "Parameter count mismatch."
Inner Exception: null
Stack Trace:

 at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
   at..//user written line info  

Any help to solve this issue or new approach to achieve same thing using System.Net.Mail will be highly appreciated.

Upvotes: 1

Views: 693

Answers (2)

Anv
Anv

Reputation: 31

To explicitly give you an answer based on first comment,

var encodeForTransport = false;
var mailWriter = mailWriterContructor.Invoke(new object[] { fileStream, encodeForTransport  });

Upvotes: 2

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131706

As I mentioned in the comments, this article is obsolete in 2020. Despite the date, it was actually written in 2009 and stopped working in 2014, when some of the internal methods changed signature. In any case, the System.Net.Mail namespace shouldn't be used because, as Microsoft strongly warns:

Important

We don't recommend that you use the SmtpClient class for new development because SmtpClient doesn't support many modern protocols. Use MailKit or other libraries instead. For more information, see SmtpClient shouldn't be used on GitHub.

MailKit (or rather the MimeKit library it's built upon) already supports saving and loading Mail messages. From Q: How do I save messages? the answer is a simple:

message.WriteTo("message.eml");

You can use MailKit's POP3 or IMAP4 clients to retrieve messages. The DownloadMessages example show how to download messages from GMail and save them:

        using (var client = new Pop3Client (new ProtocolLogger ("pop3.log"))) {
            client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect);

            client.Authenticate ("username", "password");

            for (int i = 0; i < client.Count; i++) {
                var message = client.GetMessage (i);

                // write the message to a file
                message.WriteTo (string.Format ("{0}.msg", i));

                // mark the message for deletion
                client.DeleteMessage (i);
            }

            client.Disconnect (true);
        }

Upvotes: 1

Related Questions