6

I have running Azure function App(in python language), for business requirements need to send emails from function app.

for that, I wrote a python function

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

Above block of code working fine in local machine. if I move the same code to Azure Function App it's not working.

How do I make it work on the Azure function app?

How do I send email from Gmail in Azure Function App?

peterh
  • 11,875
  • 18
  • 85
  • 108

4 Answers4

20

Sending outbound e-mail to external domains (such as outlook.com, gmail.com, etc) directly from an e-mail server hosted in Azure compute services is not supported due to the elastic nature of public cloud service IPs and the potential for abuse.  As such, the Azure compute IP address blocks are added to public block lists (such as the Spamhaus PBL).  There are no exceptions to this policy.

Since we do not support running and smtp server from our platform this should not affect us.

The only way to use EMAIL functionality as of now on Azure Web App is via an SMTP relay. A third party service such as SendGrid provides these type of services.

In the Azure Web Apps architecture the actual Web Apps sit behind common Front-Ends which are shared by all the sites hosted on that Data Centre.

There is a possibility that one of the site hosted on that datacenter is sending SPAM emails and this could have the IP address to be blacklisted by the MAIL Servers. So the e-mails sent from that address will be rejected or considered as SPAM by mail servers.   This limitation exists in case of VM or Cloud Services too. Azure uses a pool of IP Address, and these addresses are reused. That means you could get an IP Address which has already been blacklisted, as someone was sending SPAM from that address before and hence your emails would be rejected or considered as SPAM by mail servers.

This is a common scenario in Cloud and it is typically recommended to use an external Mail Service provider like SendGrid for messaging.   SendGrid related articles: 

How to Send Email Using SendGrid with Azure: https://azure.microsoft.com/en-in/documentation/articles/sendgrid-dotnet-how-to-send-email/

DixitArora-MSFT
  • 1,768
  • 1
  • 5
  • 8
  • If I have a dedicated IP address for Azure Functions with App Service plan, will using SMTP server for sending email be a good solution? Because SendGrid is not free and a 3rd party tool. – Pingpong Nov 24 '20 at 11:29
  • this is probably the best answer on StackOverflow - ever. thank you – JozeV Dec 16 '20 at 09:52
  • fyi: also you could use a Logic App SMTP module instead of a "function app". – djangofan Aug 13 '21 at 21:48
  • Then why Microsoft has a graph mail client? My understanding from here and other associated documents https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http https://damienbod.com/2021/08/09/send-emails-using-microsoft-graph-api-and-a-desktop-client/ is that you can send mails and that a SMTP server will be provided to you from the Azure portal. From what I have checked, it is not even necessary to configure a SMTP server in Azure – Alex Aug 25 '21 at 18:50
3

I would suggest you to use some 3rd party email service such as SendGrid/Twillio You can add SendGrid output binding to you Python Azure Function. The binding in function.json would look something like here

Here is an example

Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
1

Below is the actual procedure for getting sendgrid working manually with python for azure functions. This is not the optimal way since azure has it's own in house solution that may be superior to this, but this is a quick and dirty way to get it working.

run pip install sendgrid on your local machine.

In your code include:

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

Sending The Email: (keep in mind this is NOT SECURE since the API Key is Exposed, but this is quick way to get something working.)

    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')

The last step is if you want this to work on the actual azure function server you need to add this to requirements.txt

sendgrid

Note that sendgrid is free up to 25,000 emails so it works perfect for most situations. You just need to setup your API key on there website, just follow their instructions, it was simple for me to do and took about 5 minutes to create a 'user' and an API key associated with it.

Also note that I was able to send from my GMAIL account when I did this with sendgrid. HOWEVER, also note that it will go to your spam folder constantly because google can never truly verify it was you who sent from your gmail, so just keep this flaw in mind. In my case since I'm doing just testing work this doesn't matter, but it may be a problem for production work.

Joseph Astrahan
  • 8,659
  • 12
  • 83
  • 154
1

There is a hack that I'm about to implement. In my case I don't really care about the subject, attachments etc. It's an information email.

  • Add a log message in your code with email body in a parsable form.
  • Create a log based alert rule matching the log.

When Azure Monitor sees this log, it'll send an alert to the email address(es) configured in the alert. Email can include contents of log message.

As mentioned this is very restrictive:

  • can't fully control subject line
  • can't control the recipients programatically (easily at least)
  • can't attach files
Kashyap
  • 15,354
  • 13
  • 64
  • 103
  • Does it automatically include the contents of the log message or something has to be done to include it ? – dll Dec 16 '21 at 17:48
  • 1
    @dll It's a configuration of alert. If set, the alert email will contain the log message. – Kashyap Dec 16 '21 at 21:41
  • Yes thanks, works like a charm, exactly what I needed with little hassle. – dll Dec 20 '21 at 23:06
  • This is also how I trigger alerts/notifications with Application Insights. You can send custom logging messages to Application Insights and configure alerts/notifications via custom query in Application Insights. – hui chen Sep 28 '22 at 08:51