如何从 Azure 函数应用发送电子邮件?

How do I send email from an Azure function app?

我有 运行 Azure function App(python 语言),业务需求需要从 function app 发送邮件。

为此,我写了一个 python 函数

from email.message import EmailMessage
import smtplib

def send_mail():
    # message to be sent
    msg = EmailMessage()
    msg.set_content('Test content')

    msg['Subject'] = 'Test'
    msg['From'] = "test@hotmail.com"
    msg['To'] = ["test@hotmail.com"]

    # creates SMTP session 
    s = smtplib.SMTP('smtp-mail.outlook.com', 587) 
    s.ehlo()

    # start TLS for security 
    s.starttls() 
    # Authentication 
    s.login("test@hotmail.com", "password-to-login") 
      
    # sending the mail 
    s.send_message(msg)
    
    # terminating the session 
    s.quit() 

    return

以上代码块在本地机器上运行良好。如果我将相同的代码移动到 Azure Function App,它就无法正常工作。

如何让它在 Azure 函数应用程序上运行?

如何在 Azure Function App 中从 Gmail 发送电子邮件?

我建议您使用一些第三方电子邮件服务,例如 SendGrid/Twillio 您可以向 Python Azure 函数添加 SendGrid 输出绑定。 function.json 中的绑定看起来像 here

这是一个example

由于弹性特性,不支持直接从 Azure 计算服务中托管的电子邮件服务器向外部域(例如 outlook.com、gmail.com 等)发送出站电子邮件public 云服务 IP 和滥用的可能性。因此,Azure 计算 IP 地址块被添加到 public 块列表(例如 Spamhaus PBL)。此政策没有例外。

因为我们的平台不支持 运行 和 smtp 服务器,所以这应该不会影响我们。

目前在 Azure Web App 上使用 EMAIL 功能的唯一方法是通过 SMTP 中继。 SendGrid 等第三方服务提供此类服务。

在 Azure Web Apps 架构中,实际的 Web Apps 位于公共前端之后,由该数据中心托管的所有站点共享。

有可能是该数据中心托管的站点之一正在发送垃圾邮件,这可能会使 MAIL 服务器将 IP 地址列入黑名单。因此,从该地址发送的电子邮件将被邮件服务器拒绝或视为垃圾邮件。 在 VM 或云服务的情况下也存在此限制。 Azure 使用一个 IP 地址池,这些地址被重复使用。这意味着您可以获得一个已经列入黑名单的 IP 地址,因为之前有人从该地址发送垃圾邮件,因此您的电子邮件将被邮件服务器拒绝或视为垃圾邮件。

这是云中的常见场景,通常建议使用外部邮件服务提供商(如 SendGrid)进行消息传递。 SendGrid 相关文章:

如何在 Azure 中使用 SendGrid 发送电子邮件:https://azure.microsoft.com/en-in/documentation/articles/sendgrid-dotnet-how-to-send-email/

以下是使用 python 手动获取 sendgrid 以获取 azure 函数的实际过程。 这不是最佳方式,因为 Azure 拥有自己的内部解决方案,可能优于此方式,但这是一种快速但肮脏的方式来使其工作。

运行 pip install sendgrid 在您的本地计算机上。

在您的代码中包括:

from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

发送电子邮件:(请记住,这是 不安全,因为 API 密钥已暴露,但这是让某些东西工作的快速方法。)

    message = Mail(
        from_email='yourfromemail@gmail.com',
        to_emails='toemail@gmail.com',
        subject='Email Subject Line Here',
        html_content='<strong>HTML CONTENT HERE</strong>')
    try:
        sg = SendGridAPIClient('YOUR API KEY HERE')
        response = sg.send(message)
        print(response.status_code)
        print(response.body)
        print(response.headers)
    except Exception as e:
        raise Exception(str(e) + ' -> Error Reported')

最后一步是,如果您希望它在实际的 azure 函数服务器上运行,您需要将其添加到 requirements.txt

sendgrid

请注意,sendgrid 最多可免费发送 25,000 封电子邮件,因此它适用于大多数情况。您只需要在该网站上设置您的 API 密钥,只需按照他们的说明进行操作,这对我来说很简单,并且花了大约 5 分钟来创建一个 'user' 和一个 API 关联的密钥有了它。

另请注意,当我使用 sendgrid 执行此操作时,我能够从我的 GMAIL 帐户 发送。但是,还要注意它会不断地进入您的 垃圾邮件文件夹 因为 google 永远无法真正验证是您从您的 gmail 发送的,所以请记住这个缺陷。就我而言,因为我只是在做测试工作,所以这并不重要,但对于生产工作来说可能是个问题。

有一个我即将实施的 hack。就我而言,我并不真正关心主题、附件等。这是一封信息电子邮件。

  • 在您的代码中添加一条日志消息,其中包含可解析形式的电子邮件正文。
  • 创建一个 log based alert rule 匹配日志。

当 Azure Monitor 看到此日志时,它会向警报中配置的电子邮件地址发送警报。电子邮件可以包含日志消息的内容。

如前所述,这是非常严格的:

  • 无法完全控制主题行
  • 无法以编程方式控制收件人(至少很容易)
  • 无法附加文件