How do I send email from an Azure function app? - python-3.x

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?

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/

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

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.

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

Related

How Sending emails work with Azure logic apps?

when we design one logic app to send mail to required TO address list from the given mail sender(gmail, outlook), how actually the email sending works in azure logic app?
Do we need any Prerequisites like SMTP and relay service required here?
Or everything will be handled by Microsoft using logic app?
You need an SMTP server and credentials to it.
You can send emails using the connector - "SMTP" with action "Send Email (V3)"
The tricky part would be to setup the API connection for this action. Once, you have the server details on hand, you can "Add New" connection in the below screen:

SendGrid inbound parse failure with Azure deployed app

I have created a simple ASP.NET Web API app that receives parsed emails from SendGrid. Works well on my machine using a secure tunnel with ngrok. The parsed content of emails is posted to the locally hosted app.
However, when I deploy this app to Azure it does not work. I tried to use both HTTP and HTTPS for the callback URL in SendGrid, but emails are not processed. In the Activity page in SendGrid there is no entry for a Parsed email. And I get back a delivery failure email, for the email that should have been handled by SendGrid.
The response was: 550 no mailbox by that name is currently available
I know the app is reachable because I can do successful HTTP requests to other resources, from the browser or other tools.
Is there something that I might have missed? Some additional configuration, either for the app or in SendGrid?
The short answer is this:
If you use CloudFlare for your DNS, it is highly likely that CloudFlare is stopping the inbound parse posts from SendGrid.
Review your Firewall Event Log in CloudFlare (under the Firewall Tab) and see if your Web API "Host" is appearing there.
If so, what you'll need to do is whitelist the IP Address range that SendGrid uses to send posts for the inbound parse.
Their current IP range for the inbound parse as of today is 167.89.117.0/24 (basically of the IP address from 167.89.117.0 to 167.89.117.255).
Hope this helps you or someone else with this same issue/root cause.

SendGrid being blocked by Yahoo Mail server

As of a few weeks ago, I noticed that I am unable to receive emails from my domain account. My application is deployed to the azure server and it uses SendGrid to send emails and this happens from my application. For example my application is 'myapplication.com' and the azure sendgrid configuration for the mail server is set up to use 'Jake#myapplication.com' but when I send and email to my yahoo account, let say to reset my password. The email never makes it, not even going to spam. I remember reading something like this a few weeks back http://sendgrid.com/blog/update-yahoos-dmarc-policy "Yahoo New Policy" but I don't see how that would effect me since my from account is not a yahoo account. If there is no fix for this, what is an alternative email setup
Before considering an alternate email setup, contact SendGrid through support.sendgrid.com, it's possible that Yahoo is wrongly blocking your email. If this is the case SendGrid will advocate for you and work to get it unblocked.
Disclaimer: I am a SendGrid Employee
I'd suggest looking at the sendgrid dashboard and search for that email. You will be able to see exactly what happened.
it seems that Sendgrid IP pool is being deferred by yahoo. I am not sure what Sendgrid is planing to do to rectify this issue as it is impacting their clients who uses shared pool service
I have just stumbled on this issue. And it's not only Yahoo blocking sendgrid emails. They rather complaining about the senders ip address "Send Grid" rather than senders email address. :-(

Can gmail (smtp.gmail.com) post incoming mails to my application instead of my applications pulls the mail?

I am using smtp.gmail.com to send mails.
I want to read/parse mails in my application.
I know how to pull the mails, there are API libraries to handle that. It is bit over do for my application.
Instead, is there any way gmail can post mails to my application like sendgrid does ?
If you want to get emails from a gmail account, and want a webhook to do such, you could use Context.io's Webhook Feature.
However, at the maximum volume you'll be able to send out with Gmail, I'd recommend looking toward an email service provider's free plan. If you're familiar with SendGrid already SendGrid's Free Plan will give you access to both low volume sending, and the Parse webhook. Other email service providers will give you the same functionality on their free plans, as well (e.g. Mailgun).
Disclaimer: I am a SendGrid employee.

Mails for verification using Nodemailer

I want to use node-mailer module to send emails to registering users on app for verification and other purposes also. I am not sure which transport mechanism to use so that emails I send are not a spam and also get delivered.
I also want to use the same domain to receive emails regarding support and bugs(i.e lets say on email on support#example.com). I am planning to set-up google apps account for this. Basically I will set-up the google apps account with me being an user and having an alias support#example.com. So can I also set-up an alias with say admin#example.com and send the emails using nodemailer from my app using this email address? But obviously I don't want to store my email id and password for google apps in the code for security reasons. So how Should I do it?
Other option is to Amazon SES, I believe its a good service and would be very useful. But can I use the same domain name for serving email from AMAZON SES and google apps also being able to host my app? So how to send emails from AMAZON SES by authenticating SPF and DKIM so that these emails reach the inbox of the user.
Saransh,
You absolutely can use the same domain and email address with both Google Apps and AmazonSES without any issues. When it comes to receiving emails, all messages have to be directed to a single server (your MX records). But sending email is very different in that you can send email from many different sources without any issues.
To ensure your messages don't go to the SPAM folder just be sure to properly authenticate all your messages with SPF and DKIM. I'm not sure how this works with AmazonSES, but it was really easy with the provider that I chose for my email http://socketlabs.com

Resources