如何向超过15000个收件人发送邮件?

发布于 2024-11-10 15:32:11 字数 1508 浏览 1 评论 0 原文

我们正在使用asp.net 3.5和c#。我们必须制作一个强大的邮件模块。这个模块可以邮寄超过15000个收件人,或者简而言之,DBMS中的所有记录。我想问几件事。

1)我们有一个代码可以向单个收件人发送邮件。我们如何向多个收件人发送邮件。我尝试使用我们的代码通过“,”添加多个电子邮件 ID,但它只发送第一个电子邮件 ID。这是代码示例

 public bool Mail(string to, string subject, string body)
        {
            try
            {

                MailMessage objEmail = new MailMessage();
                objEmail.To =to;
                objEmail.From = "[email protected]";
                //objEmail.Priority =priority

                objEmail.Subject = subject;

                objEmail.Body = body;

                //enable the Html tag...

                objEmail.BodyFormat = MailFormat.Html;
                objEmail.Priority = MailPriority.High;

                SmtpMail.SmtpServer = "localhost";

                try
                {
                    SmtpMail.Send(objEmail);
                    return true;

                }
                catch(Exception ex)
                {
                    string error = ex.StackTrace;
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

2) 一次发送邮件的最大限制是多少。意味着我们可以在字符串中为包含 emailid 的字符串分配多少值?

3)我们的代码的一个主要内容是单击按钮,因此如果我们有超过 15000 条记录,那么它是否能够发送所有邮件,因为我们正在考虑的是该页面将有 60 秒的渲染时间,因此它可能只发送那些 id 覆盖的邮件60秒后

让我们建议最好的方法是什么。

提前致谢。

We are using asp.net 3.5 with c#.We have to make an powerful mailer module.This module can mail more than 15000 recipient or in short all records in DBMS.I would like to ask few things.

1)We have a code which sends a mail to single recipient.How will we send a mail to multiple recipient.I tried with our code to add more than one email id by ',' but it sends only first email id.Here is the code sample

 public bool Mail(string to, string subject, string body)
        {
            try
            {

                MailMessage objEmail = new MailMessage();
                objEmail.To =to;
                objEmail.From = "[email protected]";
                //objEmail.Priority =priority

                objEmail.Subject = subject;

                objEmail.Body = body;

                //enable the Html tag...

                objEmail.BodyFormat = MailFormat.Html;
                objEmail.Priority = MailPriority.High;

                SmtpMail.SmtpServer = "localhost";

                try
                {
                    SmtpMail.Send(objEmail);
                    return true;

                }
                catch(Exception ex)
                {
                    string error = ex.StackTrace;
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

2)What is the max limit to send mail at a time.Means how much value we can assign in string to that contains emailids?

3)One main thing our code is in button click so if we have more than 15000 records so will it able to send to mail all because What we are thinking is that page will have 60sec to render so it may send mails only those ids cover in 60 sec.

Lets suggest what is the best way to do that.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾城°AllureLove 2024-11-17 15:32:12

不要使用 System.Web.Mail。使用系统.Net.Mail。请参阅此博客

System.Web.Mail 已弃用且不推荐。

您需要将工作传递到实际的邮件服务器/服务上。第三方是您最好的选择。不要直接从 Web 应用程序代码发送电子邮件,因为请求超时、身份验证超时等最终将停止您的发送循环。此外,此过程将锁定当前页面/会话,直到完成/停止,并且当页面执行此类繁重任务时,我也经历过整个应用程序为所有访问者锁定的情况。

如果您想要的是一个便宜的电子邮件服务器,您可以将电子邮件添加到队列中,并且服务器只会处理它们并发送它们,那么 Amazon SES 值得一看。如果您需要更多用户管理和活动管理工具,请使用 MailChimpJangoMail 可能是您的最佳选择。

Amazon SES 绝对是最便宜的,因为您只需按使用量付费。我平均每个月花4块钱。

所有这些都提供了您可以在代码中使用的 API。

另外:请确保您的收件人以某种方式请求或期待这些电子邮件。发送垃圾邮件是违法的,处罚很严厉。

资源

另请查看以下问题:

Do not use System.Web.Mail. Use System.Net.Mail. See this blog.

System.Web.Mail is deprecated and not recommended.

You need to pass the work onto an actual mail server/service. A third party one is your best option. Do not send email directly from the web application code as request timeouts, authentication timeouts, etc will eventually halt your send loop. Also, this process will lock up the current page/session until it is done/halted and I have also experienced entire applications locking up for ALL visitors when pages are executing heavy tasks like this.

If all you want is a cheap email server that you can add emails to a queue and the server will just chug through them and send them, then Amazon SES is worth a look. If you want more user management and campaign management tools, then MailChimp or JangoMail might be your best options.

Amazon SES is definitely the cheapest as you only pay for what you use. I spend 4 bucks a month on average.

All of these provide APIs you can use in your code.

Aside: Do ensure that your recipients have somehow requested or are otherwise expecting these emails. Sending spam is illegal and the punishment is harsh.

Resources

Please also check out these questions:

我做我的改变 2024-11-17 15:32:12

除了 Chevex 答案:如果您向多个收件人发送电子邮件,请考虑使用密件抄送。如果您使用“收件人”和“抄送”,每个收件人都会看到他们可能不喜欢的其他收件人的电子邮件地址。

如果您想滚动自己的邮件发送模块而不是使用可用的服务之一,请查看此问题,了解如何在 ASP.NET 中运行寿命较长的后台任务的一些方法:在 ASP 中运行后台任务的最佳方法.Net Web 应用程序,还可以获得反馈?

Apart from Chevex answer: If you send an email to multiple recipients then consider using BCC. If you use TO and CC each recipient will see the email addresses of the other recipients which they might not appreciate.

If you want to roll your own mail sendig module instead of using one of the available services then have a look at this question for some approaches of how to run longer lived background tasks in ASP.NET: Best way to run a background task in ASP.Net web app and also get feedback?

夏花。依旧 2024-11-17 15:32:12

这是我的建议,它使用数据库来管理工作负载。

我将在这里使用 SQL Server 作为示例,因为这就是我自己一直使用的。

您要做的就是创建一个存储过程和/或指定一个表作为外发电子邮件的。除了发送电子邮件所需的表之外,该表还具有以下元数据。

SendDate
IsSent
ErrorCount
Priority

在某些时候,您需要启动一个执行实际工作的线程或进程,但如何实现这一点是有趣的。

使用 SQL Server,您可以编写如下查询:

DELCARE @now datetime; SET @now = GETDATE();

SELECT TOP (5) * 
FROM OutgoingEmail WITH (ROWLOCK, READPAST, UPDLOCK) 
WHERE SendDate < @now
    AND IsSent = 0 
    AND ErrorCount < 5
ORDER BY Priority
;

READPAST 只能在以 READ COMMITTED 或 REPEATABLE READ 隔离级别操作的事务中指定。您将在建立新连接时设置隔离级别。

现在将发生的情况是,当您使用 SqlCommand 对象创建 DataReader 时,SQL Server 将锁定这些行。其他实例无法获取它们。这意味着您现在实际上拥有一个用于发送电子邮件的工作队列。但重要的是要记住,在进行处理时必须保持连接打开,否则锁将被释放。

有几点需要注意。

  • 您获取一堆行并发送它们。如果成功设置 IsSent 位,
  • 如果崩溃(某处抛出异常),则不会丢弃电子邮件,而是会引发 ErrorCount。你不删除它,你只是增加计数。这很重要,因为如果电子邮件由于某种原因包含输入(而不是由网络连接问题引起),它可能会不断崩溃发送客户端,这称为中毒,它将防止不良数据使您的发送客户端崩溃。因此,您应该忽略 ErrorCount 较高的电子邮件。
  • 您还可以清空滚动计划并将 SendDate 向前移动,以免时不时地尝试相同的操作。
  • 瓶颈将是 SmtpClient 类,但根据您希望发送电子邮件的速度,您可以根据需要启动任意数量的代理或线程来并行处理电子邮件。
  • 优先级将确保如果您需要发送高优先级电子邮件,则不会出现队列满的问题。例如,如果您想以这种方式发送所有电子邮件,只要具有更高的优先级,就不会因为队列已满而延迟发送密码重置或注册电子邮件。

但需要注意的一件事是,当错误发生时,原因未知,我见过偶尔的网络问题导致电子邮件无法发送。使用此方法通常会发生的情况是,当网络连接或 SMTP 服务器重新联机时,电子邮件才会被发送。您还可以使用其他元数据,以便不向尝试重置其密码的用户发送多于一封电子邮件(只是因为某些未知原因目前未发送电子邮件)。

最后一件事。您可能希望将表拆分为两个或三个相同的表。这样做的原因是,如果您想在一段时间内记录发送的电子邮件,您不希望它们干扰您原本高性能的发送队列,因此您将它们移动到单独的表中,只是为了维护历史记录。处理错误也是如此,如果电子邮件最终导致错误,您可能想要记录该错误,然后可以通过将发送队列中的这些电子邮件移动到错误队列中来做到这一点。

This is my recommendation and it uses a database to manage the work load.

I'm gonna use SQL Server as an example here because that's what I've been using my self.

What you do is that you create a stored procedure and/or designate a table as the table for outgoing e-mail. This table, besides that which you need to send the email, has a the following metadata.

SendDate
IsSent
ErrorCount
Priority

At some point your going to need to fire up a thread or process that does the actual work, but how this is implemented is the interesting bit.

With SQL Server you can write a query like this:

DELCARE @now datetime; SET @now = GETDATE();

SELECT TOP (5) * 
FROM OutgoingEmail WITH (ROWLOCK, READPAST, UPDLOCK) 
WHERE SendDate < @now
    AND IsSent = 0 
    AND ErrorCount < 5
ORDER BY Priority
;

READPAST can only be specified in transactions operating at the READ COMMITTED or REPEATABLE READ isolation levels. You will set the isolation level when establishing a new connection.

Now what will happen is that when you use the SqlCommand object to create a DataReader SQL Server will lock those rows. No other instances will be able to get them. Which means you now effectively have a work queue for your outgoing email. It is however important to remember that you must keep the connection open while you do your processing otherwise the lock will be released.

A couple of things to note.

  • You fetch a bunch of rows and you send them. If you succeed your set the IsSent bit
  • If you crash (an exception is thrown somewhere) you don't discard the email you raise the ErrorCount. You don't delete it, you just raise the count. This is important because if the email for some reason contained input (as opposed to being caused by a network connectivty issue) it could keep crashing to send clients and this is called poisoning and it will prevent bad data from crashing your send clients. Therefore you should ignore email with a high ErrorCount
  • You can also empty a rolling schedule and move the SendDate forward as to not atempt the same thing every now and again.
  • The bottleneck will be the SmtpClient class but depending on the speed at which you want your emails to be sent you can spin up as many agents or threads as you need to process the emails in parallel.
  • The priority will ensure that if you need to send high priority email a full queue won't be an issue. e.g. if you wanna send all your e-mails this way, sending a password reset or registration e-mail won't be delayed just because the queue is full, as long as it has higher priority.

One thing to note though is that when errors happen the reason is unknown, I've seen the occasional network problem cause emails to not be sent. What generally will happen with this approach is that the email will just be sent at a later point when the network connectivity or SMTP server is back online. You can also have additional metadata to not send more than one email to a user who is trying to reset his or her password (just because for some unknown reason the emails are not being sent right now).

One last thing. You might want to split the table into two or three identical tables. The reason for this is that if you wanna log sent emails for a period of time you don't want them to interfere with your otherwise high performing send queue so you move them to a separate table, simply to maintain a history. It's the same deal with errors, if emails end up causing errors you might wanna log that and you can do that by then moving those emails you of the send queue into an error queue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文