Flask-Mail allows you to customize who sends the email, but when I try to do so, it just uses my login email that I used to authenticate to the server.
Example.
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = 't********3#gmail.com'
app.config['MAIL_PASSWORD'] = '********'
app.config['MAIL_DEFAULT_SENDER'] = None
app.config['DEBUG'] = True
mail = Mail(app)
#app.route('/')
def index():
msg = Message("Hello",
sender='johndoe#gmail.com',
recipients=["t*********3#gmail.com"])
mail.send(msg)
return 'message sent!'
Even though i put a sender, it still uses the ['MAIL_USERNAME'] email. Any input would be much appreciated. Thanks.
I believe this is something Google's SMTP does for you. I was able to reproduce the issue and got the same results as you: sender name was kept, but sender email was set to the google account email, no matter what the sender or default sender is.
However using a different SMTP (sendgrid) worked just fine and I can see my sender email displaying correctly.
I did not test it, but you can probably work around the issue with gmail by configuring 'Send As' in account settings and adding the email you want to be the sender here is how to do it. Or just use a different smtp.
Update: I did test it after all and it works if you add your new sender email in gmail account settings.
Related
I'm trying to send email with Python Flask but every email from my gmail account is received in the spam folder.
This is my code for send the email :
address_list = ['email#test.it']
app = Flask(__name__)
mail= Mail(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'sender#mail.it'
app.config['MAIL_PASSWORD'] = 'password'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(app)
def send_async_email(msg):
with app.app_context():
mail.send(msg)
for x in address_list:
msg = Message('Hello', sender = 'sender#mail.it', recipients = [x])
msg.body = "Hello Flask message sent from Flask-Mail"
send_async_email(msg)
print("sent")
Is there any way to prevent this from happening? maybe an option to add to make sure that the mails I send are received as normal mails ?
thank you very much
To reduce the chances that messages from your domain are sent to spam or blocked by Gmail, follow the general best practices:
This article is by google team:
Set up valid reverse DNS records of your IP addresses that point to your domain.
Ideally, send all messages from the same IP address. If you must send from multiple IP addresses, use different IP addresses for
different types of messages. For example, use one IP address for
sending account notifications and a different IP address for sending
promotional messages.
Don't mix different types of content in the same messages. For example, don't include content about promotions in purchase receipt
messages.
Messages of the same category should have the same email address in the From: header. For example, messages from a domain called
solarmora.com might have From: headers like this: Purchase receipt
messages: receipt#solarmora.com Promotional messages:
deals#solarmora.com Account notification messages: alert#solarmora.com
Check regularly to make sure your domain isn’t listed as unsafe with
Google Safe Browsing. To check your domain status, enter your domain
in the Safe Browsing site status page. Also check any domain that’s
linked to yours.
Don’t send sample phishing messages or test campaigns from your domain. Your domain’s reputation might be negatively affected, and
your domain could be added to internet blocklists. Don’t impersonate
other domains or senders without permission. This practice is called
spoofing, and it can cause Gmail to mark the messages as spam.
To help prevent valid messages from being marked as spam: Messages that have a From address in the recipient’s Contacts list are less
likely to be marked as spam. Occasionally, valid messages might be
marked as spam. Recipients can mark valid messages as not spam, so
future messages from the sender should be delivered to their inbox.
link to google article
This is how I send mail using flask and it works, so give it a try
from flask_mail import Mail, Message
# This app is: app = Flask(__name__)
from models import app
from config import SendMail
app.config.from_object(SendMail)
mail = Mail(app)
def send_mail():
msg = Message('Title')
address = 'receiver_email_id'
msg.recipients.append(str(address))
msg.body = "YOUR_MESSAGE"
mail.send(msg)
Config.py
class SendMail(object):
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USE_SSL = False
MAIL_USERNAME = 'sender_email_id'
MAIL_PASSWORD = 'password'
MAIL_DEFAULT_SENDER = 'sender_email_id'
MAIL_MAX_EMAILS = None
MAIL_ASCII_ATTACHMENTS = False
I have created python file that can send email using less secure apps turned on, but I need it off. How can I send email with 2FA?
# import simple mail transfer protocol library
import smtplib
# import EmailMessage method
from email.message import EmailMessage
contacts = ['<email#email.com>', '<email2#email.com>']
EMAIL_ADDRESS = '<my_gmail>'
EMAIL_PASSWORD = '<my_gmail_password>'
# Create empty Email Message object
msg = EmailMessage()
msg['Subject'] = 'Automated python email sender 5'
msg['From'] = EMAIL_ADDRESS
msg['To'] = contacts
msg.set_content('<sample_content>')
# contact manager we will make sure our connection is closed automatically without us doing it manually
# 465 is the port number for plain SMTP_SSL
# SMTP_SSL means you do not have to use ehlo() ans starttls()
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
smtp.send_message(msg)
What should I add to make 2FA work?
I believe you would need to set up an App passwords let you sign in to your Google Account from apps on devices that don't support 2-Step Verification. Learn more
Its basically something thats setup in the users Google account.
Another thing to look at would be Display captcha
if that doesn't work you might need to look into Xoauth2
if you require 2fa
If you want to support 2fa then you should not be using the SMTP server and should be going though the Gmail API and using Oauth2 which will prompt a user to connect via their google account and google will control the 2fa themselves. SMTP servers are not designed to handel 2fa
Try setting up App Password for your Gmail. and used that app password for smtp login.
This will help Set Up APP-Password
Under security you have to generate a password for your application:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login('demo#gmail.com', 'password generated by google')
server.sendmail('demo#gmail.com', 'demo#icloud.com', 'Mail sent from program')
print('Mail Sent')
as you can see, you enter your email but instead of typing your own password you enter the password generated by google for your application
I was wasting another day of my life messing around with python and I was thinking about how to spoof an email address using smtplib in python. I thought it could be possible to spoof the from address by using the code below but it didn't work. I have seen projects on github that seem to be able to actually spoof the email but if i were to create a program of my own that does this, how exactly would it work? Any ideas? Code:
import smtplib
username = (mygmailusername)
password = (mypassword)
fakefrom = "donaldtrump#gmail.com"
toEmail = (toAddress)
server = smtplib.SMTP("smtp.gmail.com",587)
server.starttls()
server.login(username,password)
server.sendmail(fakefrom,toEmail,"this is the fbi. OPEN UP")
server.close()
Most providers check the account with the sender address, and disallow if the sender address dosn't match with sender. Try if you have a setup box network, to use your provider network smtp server without authentification on smtp 25 port, and most of time the mail can be sent. But with that method, many receiver servers will tag directly this mail as spam/dangerous. You can try that directly in your message tool (outlook,...) it s the same behavior as you code.
Sorry I'm a bit late. The problem, here lies with the second-to-last line:
server.sendmail(fakefrom,toEmail,"this is the fbi. OPEN UP")
You are trying to use the 'fake from' address to actually send the email which isn't what you want to be doing. You just want to 'spoof' it and make the recipient think that the email came from a different address. You do that by defining the sender details in the message body.
The code that you would need to use to make this work would be:
import smtplib
username = (mygmailusername)
password = (mypassword)
fake_from = "donaldtrump#gmail.com"
fake_name = "Donald Trump"
to_email = (toAddress)
to_name = (toName)
subject = "Bonjour"
content = "This is the fbi. OPEN UP"
message = f"From: {fake_name} <{fake_from}>\nTo: {to_name} <{to_email}>\nSubject: {subject}\n\n{content}"
server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.login(username, password)
server.sendmail(username, to_email, message.encode())
server.close()
I'm trying to send an email from a Google account using Python's smtplib, but getting an error, and now I'm kind of at a loss. Google responds with the following: Please log in via your web browser and then try again. Learn more at https://support.google.com/mail/answer/78754.
The account has two factor authentication enabled, so I'm using an app specific password for my login. To my understanding, this should then work without enabling the setting for less secure apps, shouldn't it? I've been doing the same with another account while testing without a problem, but now I finally got the credentials for the proper account and there it won't accept the authentication.
I'm aware that there is a Python Gmail API thingy to use with OAuth, but if at all possible I don't want to include more packages and rewrite much, and I don't really want to enable the "less secure apps" setting either.
Is there a way to get this working without either?
If it makes a difference, here is the code I use for sending email. As said before, this was working fine with another account, so I'm not sure if it's actually relevant.
def send_mail(to_address, subject, body):
smtp_user = "myaccount#domain.com"
smtp_password = "MyAppPasswordFromGoogle"
server = "smtp.gmail.com"
port = 587
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = smtp_user
msg["To"] = to_address
msg.attach(MIMEText(body, "html"))
s = smtplib.SMTP(server, port)
s.connect(server, port)
s.ehlo()
s.starttls()
s.ehlo()
s.login(smtp_user, smtp_password)
s.sendmail(smtp_user, to_address, msg.as_string())
s.quit()
Edit:
There is an interesting difference between the two accounts: on https://myaccount.google.com/lesssecureapps, my old (working) one says "this setting isn't available for accounts that have two factor authentication enabled", while the new one says "this setting is managed by your domain administrator", even though both use 2FA and it's also forced in both domains. So I suppose there is some setting that the domain admin has to change, but I don't know which one that would be.
I tried to replicate exactly your case (with an account that has a two factor authentication enabled). After creating my app password, I used it in the code.
Anyway, I think your problem is the following:
s = smtplib.SMTP(server, port)
s.connect(server, port)
You execute the connection twice.
Try with
s = smtplib.SMTP()
s.connect(server, port)
or just this
s = smtplib.SMTP(server, port)
The entire code:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
smtp_user = 'myUser#gmail.com'
smtp_password = 'my16charactersAppPassword'
server = 'smtp.gmail.com'
port = 587
msg = MIMEMultipart("alternative")
msg["Subject"] = 'Why,Oh why!'
msg["From"] = smtp_user
msg["To"] = "destinationUser#gmail.com"
msg.attach(MIMEText('\nsent via python', 'plain'))
s = smtplib.SMTP(server, port)
s.ehlo()
s.starttls()
s.login(smtp_user, smtp_password)
s.sendmail(smtp_user, "destinationUser#gmail.com", msg.as_string())
s.quit()
As of now, google will remove the "Allow unsecure apps options" as suggested by other answers till May 30, 2022. Now you would need to generate specific app passwords.
Go to Google Accounts Page
Turn on the 2-step verification.
Security > App passwords
Select "Other apps" from the app menu.
This gives you app password. You could use the same email and this password to login with your python script
The app configuration used in a Flask Mail application (following Miguel Grinberg Flask developlemt book) :
app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
The Mail Username and Password variables have been set correctly and rechecked. While trying to send a message using the following code,
from flask.ext.mail import Message
from hello import mail
msg = Message('test subject', sender='same as MAIL_USERNAME', recipients=['check#mail.com'])
msg.body = 'text body'
msg.html = '<b>HTML</b> body'
with app.app_context():
mail.send(msg)
While sending, the application is again and again resulting in the following error:
SMTPSenderRefused: (530, '5.5.1 Authentication Required. Learn more at\n5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 qb10sm6828974pbb.9 - gsmtp', u'configured MAIL_USERNAME')
Any workaround for the error?
While digging into the issues faced, I rechecked the SMTP settings for Google,
Changing the
app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
to
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
did the trick.
Also make sure that the full username is used as Gmail SMTP username, i.e., example#gmail.com as shown in the image above.
Hope this helps!!!
I also followed this book and get the same problem, after some digging here and there, I found out the root cause of the problem. However, I am not sure whether it will be the same case for you or not.
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
As you can see your flask app gets the your email credentials through os.environ.get(), and if you set this environment variables temporarily in your system, in my case Mac OSX, after your terminal session they will be gone, so you need to set them again for the next time you enter the terminal, like below:
export MAIL_USERNAME=**YOUR EMAIL**
export PASSWORD=**YOUR PASSWORD**
I got this error because of this scenario, in order to set them permanently you need to include these variables into .bash_profile file in your home directory.
You need to change your Google account settings. On this page, turn on the option to "Allow less secure apps".
As that page says:
Some apps and devices use less secure sign-in technology, which makes your account more vulnerable. You can turn off access for these apps, which we recommend, or turn on access if you want to use them despite the risks. Learn more
Do these 2 things to resolve:
Use this link and turn on 'Allow less secure apps'- https://myaccount.google.com/lesssecureapps
Use hard-coded value for email and password and it worked fine.
Simply in the file 'init.py', edit the following section:
Don't use os.environ.get
app.config['MAIL_USERNAME'] = 'youremail#gmail.com'
app.config['MAIL_PASSWORD'] = 'yourpassword'