Я пытаюсь следовать подходу, предложенному в посте Аллана Игла в кодовом проекте. Этот же подход работал нормально до .NET Core 3.1
, но не с .NET 5.0
. Вот метод сохранения, который я создал,
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);
}
}
Я проверил все доступные базовые методы вызова и попытался работать с ними, передавая необходимые параметры, но ни один из них не работал у меня.
Сообщение об ошибке: «Несоответствие количества параметров».
Внутреннее исключение: ноль
Трассировки стека:
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
Любая помощь в решении этой проблемы или новый подход к достижению того же результата с помощью System.Net.Mail
будут высоко оценены.
Спасибо @canton7 за ваш ответ и ценное предложение.
Эта статья очень старая и просто непригодная для использования в 2020 году. Несмотря на дату, она была написана в 2009 году и фактически перестала работать в 2014 году, когда один из внутренних методов сменил подпись. Microsoft довольно сильно предупреждает, что SmptClient устарел в документации по классу, и рекомендует вместо него использовать MailKit Важно! Мы не рекомендуем использовать класс SmtpClient для новой разработки, поскольку SmtpClient не поддерживает многие современные протоколы. Вместо этого используйте MailKit или другие библиотеки.
Итак, что вы пытаетесь сделать? Забудьте об устаревшем SmtpClient и System.Net.Mail
. Что бы вы ни хотели сделать, есть лучшие способы. Именно потому, что System.Net.Mail
устарел, MailMessage
и MailWriter
не могут обрабатывать подписанные, безопасные, расширенные или составные сообщения.
Спасибо @PanagiotisKanavos за хорошо объясненный ответ. Теперь стоит обсудить это с моей командой и перейти на новую более мощную библиотеку, такую как MailKit, как вы предложили в ответе.
Несмотря на то, что я знал о том, что Microsoft предупредила его об устаревании, и были некоторые изменения во внутренних методах, я все же разместил это в стеке, потому что «System.Net.Mail» используется во многих проектах, а также позволяет избежать необходимости использования одна дополнительная внешняя библиотека. И я считаю, что получать идеи от эксперта в стеке — это всегда хорошо. Итак, стоит ли этот вопрос получить отрицательный голос? В любом случае, голоса за и против одинаково. Просто интересно, не пропустил ли я что-нибудь по вопросу.
Как я упоминал в комментариях, эта статья устарела в 2020 году. Несмотря на дату, на самом деле она была написана в 2009 году и перестала работать в 2014 году, когда у некоторых внутренних методов сменилась подпись. В любом случае пространство имен System.Net.Mail
не следует использовать, потому что, как настоятельно предупреждает Microsoft:
Важный
Мы не рекомендуем использовать класс SmtpClient для новой разработки, поскольку SmtpClient не поддерживает многие современные протоколы. Вместо этого используйте MailKit или другие библиотеки. Дополнительные сведения см. в разделе SmtpClient не следует использовать на GitHub.
MailKit (или, скорее, библиотека MimeKit, на которой он построен) уже поддерживает сохранение и загрузку почтовых сообщений. От В: Как сохранить сообщения? ответ прост:
message.WriteTo("message.eml");
Вы можете использовать клиенты MailKit POP3 или IMAP4 для получения сообщений. В примере DownloadMessages показано, как загружать сообщения из GMail и сохранять их:
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);
}
Чтобы явно дать вам ответ на основе первого комментария,
var encodeForTransport = false;
var mailWriter = mailWriterContructor.Invoke(new object[] { fileStream, encodeForTransport });
Конструктор MailWriter теперь принимает 2 параметра. Не используйте отражение для доступа к внутренним типам, подобным этому: они могут сломаться даже между второстепенными выпусками.