0

我正在尝试通过 sendasync 发送电子邮件。问题是它似乎没有进入 sendcompleted 事件处理程序。我在那里添加了一个断点,但它永远不会触发。该程序只是等待我的信号量。有任何想法吗?该程序是一个 Windows 窗体应用程序。

if (send)
          {
                    print("Starting to send mail to " + Globalcls.projects[i].name);
                    mailSendSemaphore = new Semaphore(0, 1);
                    System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
                    msg.To.Add(Globalcls.projects[i].email);
                    msg.From = new MailAddress(Globalcls.settings.server_email);
                    msg.Subject = "Data";
                    msg.SubjectEncoding = System.Text.Encoding.UTF8;
                    msg.Body = "Please see attached data";
                    msg.BodyEncoding = System.Text.Encoding.UTF8;
                    msg.IsBodyHtml = false;
                    msg.Priority = MailPriority.High;

                    foreach (string fileName in files)
                    {
                       msg.Attachments.Add(new System.Net.Mail.Attachment(fileName));
                    }


                    SmtpClient client = new SmtpClient();
                    client.Credentials = new System.Net.NetworkCredential(Globalcls.settings.username, Globalcls.settings.password);
                    client.Port = Convert.ToInt32(Globalcls.settings.portS);//or use 587 

                    client.Host = "smtp.xdsl.co.za";

                    client.SendCompleted += new SendCompletedEventHandler(MailSendCallback);

                    client.SendAsync(msg,null);
                    mailSendSemaphore.WaitOne();
                   // if (Globalcls.error_message != "")
                      //  throw Exception
                    //client.Dispose();
                    print("email sent to " + Globalcls.projects[i].name);
                    client.Dispose();
                    mailSendSemaphore.Dispose();
                    msg.Dispose();

                }

                //Array.ForEach(Directory.GetFiles(GlobalClass.projects[i].foldero), delegate(string path) { File.Delete(path); });
                System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(Globalcls.projects[i].foldero);
                foreach (System.IO.FileInfo file in directory.GetFiles()) file.Delete();
                foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);


            }

这是我的 onsendcomplete 偶数处理程序

        private static void MailSendCallback(object sender, AsyncCompletedEventArgs arg)
    {
        // oncomllete event for async send.
        if (arg.Error != null)
        Globalcls.error_message = arg.Error.ToString();

        // Release the main thread
        mailSendSemaphore.Release();
    }

编辑

我想使用 sendasync 的原因是 send async 显然会等待文件上传完成。当前的问题是有时附件太大以至于上传时间比超时时间长。我可以延长超时时间,但我不知道我应该做多长时间。大多数电子邮件很容易达到 3mb。而且我们的 adsl 产品线并不总是最稳定的。

等待发送异步的原因是每个客户端不能有多个发送。这就是为什么我等待它完成。

我的问题与超时有关。我想要一个超时,只有当 smtp 和 smtp 客户端之间没有通信时才会超时。

编辑 2

这就是我的代码最初的样子。我想尽量避免这种大规模的超时。让它多线程只会使 gui 不会挂起。

if (send)
                {
                    print("Starting to send mail to " + Globalcls.projects[i].name);
                  //  mailSendSemaphore = new Semaphore(0, 1);
                    System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
                    msg.To.Add(Globalcls.projects[i].email);
                    msg.From = new MailAddress(Globalcls.settings.server_email);
                    msg.Subject = "Data";
                    msg.SubjectEncoding = System.Text.Encoding.UTF8;
                    msg.Body = "Please see attached data";
                    msg.BodyEncoding = System.Text.Encoding.UTF8;
                    msg.IsBodyHtml = false;
                    msg.Priority = MailPriority.High;

                    foreach (string fileName in files)
                    {
                       msg.Attachments.Add(new System.Net.Mail.Attachment(fileName));
                    }


                    SmtpClient client = new SmtpClient();
                    client.Credentials = new System.Net.NetworkCredential(Globalcls.settings.username, Globalcls.settings.password);
                    client.Port = Convert.ToInt32(Globalcls.settings.portS);//or use 587 

                   // client.Host = "127.0.0.1";
                    client.Host = "smtp.xdsl.co.za";
                    client.Timeout = 400000;
                    client.Send(msg);

                   /* client.SendCompleted += new SendCompletedEventHandler(MailSendCallback);

                    client.SendAsync(msg,null);
                    mailSendSemaphore.WaitOne();*/
                   // if (Globalcls.error_message != "")
                      //  throw Exception

                    print("email sent to " + Globalcls.projects[i].name);
                    client.Dispose();
                   //mailSendSemaphore.Dispose();
                    msg.Dispose();

                }

                //Array.ForEach(Directory.GetFiles(GlobalClass.projects[i].foldero), delegate(string path) { File.Delete(path); });
                System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(Globalcls.projects[i].foldero);
                foreach (System.IO.FileInfo file in directory.GetFiles()) file.Delete();
                foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);


            }
            catch (Exception ex)
            {
                print("Error with " + Globalcls.projects[i].name);
                print(ex.ToString());
                timer1.Enabled = false;
                timer1.Stop();
                btn_start.Enabled = true;
                string contents = "There was an error in sending mail to " + Globalcls.projects[i].name;
                string heading = " Anxo error";
                string subject = "Anxo error";
                errormail(heading, subject, contents, ex.ToString(), Globalcls.projects[i].sos);
                result = false;
            }
4

1 回答 1

0

安装 IIS/SmtpService 并让它处理上传。即用于SmtpClient将电子邮件发送到localhost:25= 本地 IIS。

恕我直言,您这样做会得到更可靠的解决方案。因为如果出现故障,IIS 将继续尝试上传消息。

更新

像这样的东西:

public class EmailSender
{
    ConcurrentQueue<MailMessage> _queue = new ConcurrentQueue<MailMessage>();
    private Thread _worker;
    ManualResetEvent _trigger = new ManualResetEvent(false);
    private bool _shutdown;

    public EmailSender()
    {
        _worker = new Thread(SendEmails);
        _worker.Start();
    }
    public void Enqueue(MailMessage message)
    {
        _queue.Enqueue(message);
        _trigger.Set();
    }

    public void Shutdown()
    {
        _shutdown = true;
        _trigger.Set();
        _worker.Join();
    }

    private void SendEmails(object state)
    {
        while (true)
        {
            _trigger.WaitOne(Timeout.Infinite);
            if (_shutdown)
                return; // you might want to send all emails instead.

            MailMessage msg;
            if (!_queue.TryDequeue(out msg))
            {
                _trigger.Reset();
                continue;
            }

            SendEmail(msg);
        }
    }

    private void SendEmail(MailMessage msg)
    {
        var client = new SmtpClient(); // configure
        try
        {
            client.Send(msg);
        }
        catch(SmtpException)
        {
            // try again. You might not want to retry forever = fix
            _queue.Enqueue(msg);
        }

    }
}
于 2012-09-11T06:03:30.563 回答