I'm trying to write a separate mail service, which is decoupled with our Flask application. I'm looking for a way to send welcome emails when users first log into our Flask application. I'm using Celery and RabbitMQ to do it asynchronously.
Here is my email function:
sen = 'example#gmail.com'
pwd = 'my_password'
#celery.task
def send_email(nickname, email):
msg = MIMEMultipart('alternative')
msg['Subject'] = 'my_sub'
msg['From'] = sen
msg['To'] = email
html = <b>test_body</b>
part1 = MIMEText(html, 'html')
msg.attach(part1)
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(sen, pwd)
server.sendmail(sen, [email], msg.as_string())
server.close()
Initially I was using Flask's render_template to get the HTML body and subject. But I don't want to use the Flask extension (I have my reasons). So my questions are:
How can I use email templates so that the subject and body fields can be configured easily?
How can I put the default email sender and password in a config file/email template (might be related to q1)?
It seems to be that I have a lot of code to send a simple email. Can you suggest some optimization techniques (omitting steps)?
I've wrritten a simple module(mail.py) to send emails using templates(HTML/TEXT). Hope that helps!
https://github.com/ludmal/pylib
It may be simpler to use an external service.
A service (e.g. Mailchimp) is simple to integrate. You can design the template in their layer, and trigger emails by sending merge data from your app to the service API. Functionally it's a lot like rendering a template locally and mailing it out via SMTP, but they have sophisticated tools for adapting message format to devices, tracking bounces, improving deliverability, reporting etc.
Services like this often have a free tier for up to 1000's of emails per month.
Related
Just like many big companies using Office365, my company is using google (gsuite) to host their email domain. I need to send automated emails to multiple people within organisation using a python script. How can that be done?
You can use a 3rd party service like Mailgun, it provides a REST API which if you hit you can trigger emails that it will send from a custom domain you configure on the service.
Its super easy to use for python, I use it for Raspberry Pi projects.
def send_simple_message():
return requests.post(
"https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
auth=("api", "YOUR_API_KEY"),
data={"from": "Excited User <mailgun#YOUR_DOMAIN_NAME>",
"to": ["bar#example.com", "YOU#YOUR_DOMAIN_NAME"],
"subject": "Hello",
"text": "Testing some Mailgun awesomness!"})
It is a nice alternative to using a corporate SMTP server.
Got it fixed.
In order to send an email from Python, we first need to switch ON "Less secure app access" https://myaccount.google.com/lesssecureapps?utm_source=google-account&utm_medium=web.
This we need to do if we don't have 2 Factor Authentication.
If you use 2 Factor Authentication, then you need to create an App Password and use that particular password while sending an email and not your regular password.
To create an App Password use this link: https://support.google.com/mail/answer/185833?hl=en
Now using sample script like below, we can send an email.
import smtplib
# creates SMTP session
s = smtplib.SMTP('smtp.gmail.com', 587)
# start TLS for security
s.starttls()
# Authentication
s.login("username#domain.com", "app_password")
# message to be sent
message = "Message_you_need_to_send"
# sending the mail
s.sendmail("username#domain.com", "recipient#domain.com", message)
# terminating the session
s.quit()
Google provides Gmail api suite for python and it is the preferred way to access versus smtp login/password
You should refer to their developer console for examples and tutorials
I am trying to send an email from a custom domain in Python. I have figured out how to send emails from other domains, like gmail.com, using smtplib [example code]. Now I want to figure out how to send an email from a custom domain like catsareonwheels.com.
I thought I would be able to use smtpd to send emails from a server, but that library appears only to serve as a proxy fora Mail Transfer Agent. From what I can tell, there are MTA's written in Pure Python [e.g. Slimta], but I have not been able to find any examples of snippets that actually demonstrate how to send an email from a custom domain with Python.
If anyone can help point me toward literature that might help me determine how best to achieve this goal, I'd be very grateful.
TO SEND AN EMAIL FROM A CUSTOM DOMAIN, YOU DO THE FOLLOWING:
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
msg = MIMEMultipart()
msg["From"] = "<your_mail_account>"
msg["To"] = "<destiny_account>"
body_text = "HOLA MUNDO :)"
body_part = MIMEText(body_text, 'plain')
msg.attach(body_part)
with smtplib.SMTP(host="smtp.<CUSTOM_DOMAIN>.com", port=587) as smtp_obj: # ENVIAR DESDE UN DOMINIO PERSONALIZADO.
smtp_obj.ehlo()
smtp_obj.starttls()
smtp_obj.ehlo()
smtp_obj.login("<your_mail_account>", "<your_password>")
smtp_obj.sendmail(msg['From'], [msg['To'],], msg.as_string())
print("¡Datos enviados con éxito!")
That's all :) Hope you like it!
After trying all the SMTP server settings that I have found on other posts I have found the right settings browsing through domain cPanel:
Go to "List Email Accounts"
On the right sido of the account you want to use click on "Connect devices"
Check "Mail Client Manual Settings"
What do you exactly mean by "custom domain"?
If you have some hosting witch provides you an email service then you can use smtplib as well.
Lets say I bought a hosting and a domain use-smtplib.com. I've created an email account myname#use-smtplib.com in admin panel.
Then configuration should look somehow like this:
with smtplib.SMTP_SSL('mail.use-smtplib.com', '465') as smtp:
smtp.login('myname#use-smtplib.com', 'my_strong_password')
subject = "Message from python"
msg = "Hello from python"
smtp.sendmail('myname#use-smtplib.com', 'recipient#gmail.com', msg)
Exact configuration may be different depending on your email provider. Domains starting with mail.domain.com and smtp.domain.com are pretty common.
EDIT: The main error is when this script runs from different IP / Wifi or whatever. It will just cancel it like skip over it or whatever.
I'm trying to send an email with text that says something. (or I can insert a variable for example: score = 32 and I would put 'score' in body without the ' '.)
The following code is what I'm using:
import smtplib
gmail_user = 'name#gmail.com'
gmail_password = 'password'
sent_from = gmail_user
to = 'me#gmail.com'
subject = 'OMG Super Important Message'
body = 'blah blah blah this is a message'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print 'Email sent!'
except:
print 'Something went wrong...'
So where it says 'body' I can put like a variable not just a text and it would send. But now,
when I send a program to someone and they go through the steps until this and the script will just skip it because the print 'loaded successful' one won't print meaning it didn't work. Any help on how to fix?
You'll have to enable less secure apps in order to access your gmail account via smtplib.
Let less secure apps access your account
If an app or device doesn’t meet our security standards, Google will block anyone who tries to sign in from that app or device. Because these apps and devices are easier to break into, blocking them helps keep your account safe.
Some examples of apps that do not support the latest security standards include:
The Mail app on your iPhone or iPad with version 6 or below
The Mail app on your Windows phone preceding the 8.1 release
Some Desktop mail clients like Microsoft Outlook and Mozilla Thunderbird
Change account access for less secure apps
To help keep Google Accounts through work, school, or other groups more secure, we block some less secure apps from using them. If you have this kind of account, you’ll see a "Password incorrect" error when trying to sign in. If so, you have two options:
Option 1: Install a more secure app that uses stronger security measures. All Google products, like Gmail, use the latest security measures.
Option 2: Change your settings to allow less secure apps into your account. We don't recommend this option because it can make it easier for someone to break into your account. If you want to allow access anyway, follow these steps:
Go to the "Less secure apps" section of my Account.
Turn on Allow less secure apps. (Note: If your administrator has locked less secure app account access, this setting is hidden.)
If you still can't sign in to your account, learn more about the "password incorrect" error.
I have been writing a simple app to test how to send emails via an SMTP method (needs to be SMTP to be portable to different SMTP services) using Flask-Mail. For this I am trying to use Mailgun through Heroku, but after much trial, error and research I still cannot seem to get emails to send.
My question is on a similar vein to this question, Flask on Heroku with MailGun config issues, however I can see no resolution in this question other than to use Mailgun's API, which isn't feasible for the project I am working on.
Currently I have the flask/flask-mail code set up as follows (stripped down of course):
from flask import Flask
from flask.ext.mail import Mail
from flask.ext.mail import Message
app = Flask(__name__)
mail = Mail(app)
app.config.setdefault('SMTP_SERVER', environ.get('MAILGUN_SMTP_SERVER'))
app.config.setdefault('SMTP_LOGIN', environ.get('MAILGUN_SMTP_LOGIN'))
app.config.setdefault('SMTP_PASSWORD', environ.get('MAILGUN_SMTP_PASSWORD'))
app.config.setdefault('MAIL_SERVER', environ.get('MAILGUN_SMTP_SERVER'))
app.config.setdefault('MAIL_USERNAME', environ.get('MAILGUN_SMTP_LOGIN'))
app.config.setdefault('MAIL_PASSWORD', environ.get('MAILGUN_SMTP_PASSWORD'))
app.config.setdefault('MAIL_USE_TLS', True)
def EmailFunction(UserEmail):
msg = Message("Hello",
sender='testing#test.com',
recipients=[UserEmail])
msg.html = "<b>testing</b>"
mail.send(msg)
return msg.html
#app.route('/EmailTest/')
def EmailTestPage():
EmailFunction('developer#test.com')
return 'Email Sent'
if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)
Am I missing something? And is there a way to test what is going wrong as the code passes and 'Email Sent' is returned, but no email is sent/received seemingly.
Thanks for any help you can provide!
It looks like you're not reading in the SMTP port. By default Flask mail likely tries to use 25 whereas mailgun uses 587.
In PHP I can send an email simply by calling mail(). In Django, I need to specify SMTP backends and other things.
Is there a simpler way to send email from Django?
There are several good mail-sending functions in the django.core.mail module.
For a tutorial please see Sending e-mail:
Although Python makes sending e-mail
relatively easy via the smtplib
library, Django provides a couple of
light wrappers over it. These wrappers
are provided to make sending e-mail
extra quick, to make it easy to test
e-mail sending during development, and
to provide support for platforms that
can’t use SMTP.
The simplest function that would most likely suit your purposes is the send_mail function:
send_mail(
subject,
message,
from_email,
recipient_list,
fail_silently=False,
auth_user=None,
auth_password=None,
connection=None)
In PHP you can only send mail with a simple mail() command on non-Windows systems. These will expect a local MTA like Postfix to be installed and correctly configured, as should be the case for most web servers. If you want to depend on third-party or decentralized mail service depends on how critical email is for your application. Serious dependency on speedy and reliable email transmission usually results in sending mail via SMTP to a central mail server (the "big pipe").
Still, if you want to have the same function as in PHP, try this:
import subprocess
def send_mail(from_addr, to_addr, subject, body):
cmdline = ["/usr/sbin/sendmail", "-f"]
cmdline.append(from_addr)
cmdline.append(to_addr)
mailer = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
dialog = "From: %s\nTo: %s\nSubject: %s\n\n%s\n.\n" % (from_addr, to_addr, subject, body)
return mailer.communicate(dialog)
And use it like:
send_mail ("Me <myself#mydomain.com>", "Recip Ient <other#hisdomain.com>", "Teh' Subject", "Mail body")
Either way, you need some backend (read MTA). Of the top of my head I can think of two things:
As already pointed out, you can for example use sendmail http://djangosnippets.org/snippets/1864/
Even better, use a Python MTA. There's Lamson, a Python email server (MTA): http://lamsonproject.org/docs/hooking_into_django.html