【问题标题】:How to send email from a Windows service?如何从 Windows 服务发送电子邮件?
【发布时间】:2011-01-26 00:05:54
【问题描述】:

我需要按计划发送大量电子邮件(可能每天数百封)。我想这样做的方式如下,但问题是我的 Body 字段可能会变得非常大,如果我将它添加为字符串,它会变得很难看。

SmtpClient client = new SmtpClient(); //host and port picked from web.config
client.EnableSsl = true;

MailMessage message = new MailMessage();

message.Body = "test from winservice"; // HERE IS MY PROBLEM
message.IsBodyHtml = true;
message.From = new MailAddress("donotreply@abcde.com");
message.Subject = "My subject";
message.To.Add(new MailAddress("piniusha@abcde.com"));
try
{
    client.Send(message);
}
catch (Exception)
{
   
}

当我不得不从一个 aspx 页面执行此操作时,我使用了:

MailDefinition message = new MailDefinition();  
        
message.BodyFileName = @"~\EmailTemplate\Template1.htm";
ListDictionary replacements = new ListDictionary();
replacements.Add("<% Name %>", this.txtName.Text);
replacements.Add("<% PhoneOrEmail %>", this.txtPhoneOrEmail.Text);
replacements.Add("<% Message %>", this.txtMessage.Text);
MailMessage msgHtml = message.CreateMailMessage(RECIPIENTS, replacements, new LiteralControl());

我认为这是一个优雅的解决方案,但我不想引用System.Web.UI.WebControls.MailDefinition ,因为我在 Winservice。

  1. 如何从 Winservice 发送批量电子邮件?
  2. 是否可以从 Gmail 帐户发送电子邮件?或者他们会在一段时间后阻止我?

【问题讨论】:

  • 我相信 GMail 在 24 小时内有 500 个收件人的限制。但是,我不鼓励将 GMail 用于批量电子邮件;它可能违反他们的服务条款。
  • 谢谢瑞恩,这是一个更详细地解释它的帖子labnol.org/internet/email/gmail-daily-limit-sending-bulk-email/…所以我想我将不得不停止使用gmail发送电子邮件:(

标签: c# .net email windows-services smtp


【解决方案1】:

您为什么不使用与 MailDefinition 完全相同的概念?从模板文件加载正文,用另一个列表中的文本替换一些标记 - 邮件合并样式?

您所做的只是对要与模板合并的信息数据集进行 foreach。加载合并数据,遍历合并数据,用当前合并记录替换模板中的标记。将消息体设置为当前构建的消息。将消息附加到消息队列或立即发送,任您选择。

这不是火箭科学。您已经获得了创建消息的代码,因此这只是加载合并数据并循环遍历它的情况。我已经简化以演示这个概念,我使用 CSV 来处理合并数据,并假设没有字段包含任何逗号:

message.IsBodyHtml = true;
message.From = new MailAddress("MailSender@MyCompany.com");
message.Subject = "My bogus email subject";

string[] lines = File.ReadAllLines(@"~\MergeData.csv");
string originalTemplate = File.ReadAllText(@"~\Template.htm");

foreach(string line in lines)
{
    /* Split out the merge data */
    string[] mergeData = line.Split(',');

    /* Reset the template - to revert changes made in previous loop */
    string currentTemplate = originalTemplate;

    /* Replace the merge tokens with actual data */
    currentTemplate = currentTemplate.Replace("[[FullNameToken]]", mergeData[0]); 
    currentTemplate = currentTemplate.Replace("[[FirstNameToken]]", mergeData[1]);
    currentTemplate = currentTemplate.Replace("[[OtherToken]]", mergeData[2]);

    /*... other token replacements as necessary.
     * tokens can be specified as necessary using whatever syntax you choose
     * just make sure that there's something denoting the token so you can
     * easily replace it */

    /* Transfer the merged template to the message body */
    message.Body = currentTemplate;

    /* Clear out the address from the previous loop before adding the current one */
    message.To.Clear();
    message.To.Add(new MailAddress(mergeData[3]));
    client.Send(message);
}

【讨论】:

  • 我在想还有另一种方法,而不是将 htm 作为字符串加载并替换标记。但我想没有。感谢您的回答。
  • @UshaP - 加载 htm 的方法有很多,但并不总是归结为“最聪明的做法是什么”。通常最简单的方法是最好的。您可以(正如其他人建议的那样)将 htm 作为 XML 文档加载并使用 XPath 来查询和设置值。我会说这完全是矫枉过正,在这种特殊情况下太聪明了。
  • 也许这是一个微不足道的问题,但我不知道如何动态地采用我的 htm 路径。我有一个引用 BL 类库项目的 Windows 服务,我把我的 htm 文件放在那里。 File.ReadAllText 我正在寻找 'C:\Windows\system32\..
  • 在 app.config 文件中设置路径,这样您就不会将其硬编码到预先指定的位置。如果它在本地目录中,只需使用文件名,即“MyTemplate.htm”,您也可以使用相对位置“.\Templates\MyTemplate.htm”或“..\Templates\MyTemplate.htm”或绝对路径,例如“C:\MyTemplates\MyTemplate.htm”。你得到 C:\Windows\System32\... 的原因是因为我认为“~\”前缀。在表示应用程序根的 ASP.NET 应用程序中。 Windows 服务应用程序中的 IIRC,它引用 System32 目录(?)
  • 感谢您的回复。这就是我最终要做的事情:我将复制到输出目录设置为如果在我的模板文件夹上更新,则复制。然后 string executablePath = Process.GetCurrentProcess().MainModule.FileName; string templatePath = string.Format("{0}\\EmailTemplate\\MatchupsReady.htm", Path.GetDirectoryName(executablePath));
【解决方案2】:

一个简单的答案是这样的:

message.Body = File.ReadAllText(@"~\EmailTemplate\Template1.htm");

我不确定你的具体观点,但我相信其他人会回答这些问题:)

【讨论】:

    【解决方案3】:

    使用有什么问题

    "messageBody".Replace("", curr.Name).Replace(....)...
    ?

    至于来自 gMail 的 sendign,您可以通过 SMTP 进行,但他们不会让您欺骗另一个“发件人”地址,因此收件人会看到它来自 gMail 地址。

    【讨论】:

      【解决方案4】:

      我会使用一些模板引擎。以StringTemplate 为例。

      【讨论】:

      • 哇,那个网站很难看。
      猜你喜欢
      • 1970-01-01
      • 2017-08-05
      • 2012-10-09
      • 2017-08-25
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多