[英]Send email when using SmtpClient
我創建了發送失敗的電子郵件的循環
我讀過,在代碼中使用thread.sleep不是最佳實踐,因為這可能會導致問題。 但是,有用於smtp客戶端的客戶端,該客戶端在發送消息之前先處理事務。 我如何才能更好地將其用於Web應用程序?
using (var SmtpClient = new SmtpClient()) {
bool success = false;
int attemts = 0;
const int maxAttempts = 5;
do {
try {
SmtpClient.Send(mailMessage);
System.Threading.Thread.Sleep(400);
success = true;
} catch{
// ok wait for request
success = false;
attemts ++;
}
} while (success && (attemts == maxAttempts));
}
我想補充丹尼斯的答案。
這里是SmtpClient包裝器的簡化實現,它允許您將重試計數參數與SendAsync方法一起使用:
public class EmailSender {
private int _currentRetryCount;
private int _maxRetryCount;
private MailMessage _mailMessage;
private bool _isAlreadyRun;
public event SendEmailCompletedEventHandler SendEmailCompleted;
public void SendEmailAsync(MailMessage message, int retryCount) {
if (_isAlreadyRun) {
throw new InvalidOperationException(
"EmailSender doesn't support multiple concurrent invocations."
);
}
_isAlreadyRun = true;
_maxRetryCount = retryCount;
_mailMessage = message;
SmtpClient client = new SmtpClient();
client.SendCompleted += SmtpClientSendCompleted;
SendMessage(client);
}
private void SendMessage(SmtpClient client) {
try {
client.SendAsync(_mailMessage, Guid.NewGuid());
} catch (Exception exception) {
EndProcessing(client);
}
}
private void EndProcessing (SmtpClient client) {
if (_mailMessage != null) {
_mailMessage.Dispose();
}
if (client != null) {
client.SendCompleted -= SmtpClientSendCompleted;
client.Dispose();
}
OnSendCompleted(
new SendEmailCompletedEventArgs(null, false, null, _currentRetryCount)
);
_isAlreadyRun = false;
_currentRetryCount = 0;
}
private void SmtpClientSendCompleted(object sender, AsyncCompletedEventArgs e) {
var smtpClient = (SmtpClient)sender;
if(e.Error == null || _currentRetryCount >= _maxRetryCount) {
EndProcessing(smtpClient);
} else {
_currentRetryCount++;
SendMessage(smtpClient);
}
}
protected virtual void OnSendCompleted(SendEmailCompletedEventArgs args) {
var handler = SendEmailCompleted;
if (handler != null) {
handler(this, args);
}
}
}
public delegate void SendEmailCompletedEventHandler(
object sender, SendEmailCompletedEventArgs e);
public class SendEmailCompletedEventArgs : AsyncCompletedEventArgs {
public SendEmailCompletedEventArgs(
Exception error,
bool canceled,
object userState,
int retryCount)
: base(error, canceled, userState) {
RetryCount = retryCount;
}
public int RetryCount { get; set; }
}}
下面也是消費者代碼示例:
var sender = new EmailSender();
sender.SendEmailCompleted += (o, eventArgs)
=> Console.WriteLine(eventArgs.RetryCount);
sender.SendEmailAsync(new MailMessage(), 5);
上面的代碼片段中有很多簡化,但是您應該了解主要思想。
我不確定您為什么需要此功能,但是我假設您要確保發送電子郵件。
以我的經驗,最好讓電子郵件服務器(或服務)處理電子郵件。 電子郵件服務器旨在重試傳遞,直到傳遞成功或永久失敗。 如果您選擇本地(例如IIS的內置電子郵件服務)或附近(例如您的ISP)的電子郵件服務器,則應該保證它始終可用。 配置SmtpClient
以在此處發送電子郵件。 由於服務器是關閉的,因此這應該不會失敗,也不會花費很長時間,從而消除了在應用程序中重試的需要。
無論如何,我建議您實施日志記錄以跟蹤任何無法發送的電子郵件。
您可以使用SmtpClient.SendAsync()
異步發送郵件
將指定的電子郵件發送到SMTP服務器進行傳遞。 此方法不會阻塞調用線程,並允許調用方將對象傳遞給操作完成時要調用的方法。 -MSDN
這並不像您想的那么容易。 編寫起來很容易,但是要使其真正起作用是很棘手的:)。 我建議您看看此SMTP發送器 。 我花了一些時間嘗試編寫自己的電子郵件發件人,但最終找到了這個工作庫。 我遇到的問題之一就是使用GMail,此問題已在此處解決。 我沒有與作者保持任何聯系,但我強烈建議您這樣做。
順便說一句,是的,.Net似乎為您提供了所有內容,沒有理由使用外部庫,但是嘗試幾次后,請記住這篇文章並嘗試一下。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.