Sending an email with Flask - python

I am following Flask Web Development book by Miguel Grinberg and I ran into an issue with his Email chapter.
These are his configurations:
import os
# ...
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")
After I set my environment variables I go into shell and try to run the following code:
(venv) $ flask shell
>>> from flask_mail import Message
>>> from hello import mail
>>> msg = Message("test email", sender="you#example.com", recipients=["you#example.com])
>>> msg.body = "This is plain text body"
>>> msg.html = "This is <b>HTML</b> body"
>>> with app.app_context():
... mail.send(msg)
...
My gmail is set up correctly, I followed the tutorial and did all the steps mentioned.
My code produced the following error:
Traceback (most recent call last):
File "<console>", line 2, in <module>
File "c:\...\flasky\venv\lib\site-packages\flask_mail.py", line 491, in send
with self.connect() as connection:
File "c:\...\flasky\venv\lib\site-packages\flask_mail.py", line 144, in __enter__
self.host = self.configure_host()
File "c:\...\flasky\venv\lib\site-packages\flask_mail.py", line 158, in configure_host
host = smtplib.SMTP(self.mail.server, self.mail.port)
File "C:\...\Python\Python37\lib\smtplib.py", line 251, in __init__
(code, msg) = self.connect(host, port)
File "C:\...\Python\Python37\lib\smtplib.py", line 336, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "C:\...\Python\Python37\lib\smtplib.py", line 307, in _get_socket
self.source_address)
File "C:\...\Python\Python37\lib\socket.py", line 727, in create_connection
raise err
File "C:\...\Python\Python37\lib\socket.py", line 716, in create_connection
sock.connect(sa)
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or
established connection failed because connected host has failed to respond
I found another question that was raised about the same thing and I tried a couple of things that were suggested in there:
I changed the line
app.config["MAIL_SERVER"] = "smtp.googlemail.com"
to
app.config["MAIL_SERVER"] = "smtp.gmail.com"
and I hard coded "MAIL_USERNAME" and "MAIL_PASSWORD" variables but I got the same error again.
Due to nothing working and the previous question about this being very old (4 years) I thought it might be worth raising this again.
If anybody knows what I am doing wrong please let me know.
Thanks

Make sure you have allowed less secure apps to connect to your Google account.
Here is the link: https://myaccount.google.com/lesssecureapps

Try it with the following params:
app.config["MAIL_SERVER"] = "smtp.gmail.com"
app.config["MAIL_PORT"] = 465

Below is an example that works for me:
import os
from flask import Flask, jsonify
from flask_mail import Mail, Message
app = Flask(__name__)
app.config["MAIL_SERVER"]='smtp.gmail.com'
app.config["MAIL_PORT"]=587
app.config["MAIL_USE_TLS"]=False
app.config["MAIL_USE_SSL"]=True
app.config["MAIL_USERNAME"]=os.environ.get("MAIL_USERNAME")
app.config["MAIL_PASSWORD"]=os.environ.get("MAIL_PASSWORD")
mail = Mail(app)
msg = Message(
<your subject>,
sender=os.environ.get("MAIL_USERNAME"),
recipients=<recipiente e-mail>,
html=<your html template>
)
#app.route('/sendmail')
def publish():
mail.send(msg)
return jsonify({'message': 'Your message has been sent successfully'}), 200
if __name__ == '__main__':
app.run()

Related

Django send_mail not working while smtplib works

I have a setup where I am using "send_mail" to send emails to the users using a gmail account. For some reason this function returns "smtplib.SMTPServerDisconnected: Connection unexpectedly closed".
I am using a gmail account with 2 factor security enabled and an app password.
If I just build a script using smtplib, it works. I am not sure how exactly to debug this issue.
Edit 1:
'send_mail' Seems to work if I remove "**connection_params" from being passed to "self.connection_class" on line 81 in 'django/core/mail/backends/smtp.py'
Edit 2:
Changing "smtpObj = smtplib.SMTP('smtp-relay.gmail.com', 587)" to "smtpObj = smtplib.SMTP('smtp-relay.gmail.com', 587, local_hostname='localhost')" results in the same error in case of smtplib
The problems seems to lie in the following:
value "localhost" is assigned to "connection_params" on line 69 in 'django/core/mail/backends/smtp.py' in the following manner (you may notice, there is no 'if' check, as the comment states):
...
# If local_hostname is not specified, socket.getfqdn() gets used.
# For performance, we use the cached FQDN for local_hostname.
connection_params = {"local_hostname": DNS_NAME.get_fqdn()}
...
The problem is, there is no way to assign 'local_hostname', as far as I can see, nor is there a way to set it to None
Edit 3:
It looks like Django is trying to do a 'socket.getfqdn()', which returns 'localhost', but 'localhost' is not fully qualified. Smtplib does the same 'socket.getfqdn()', but check for localhost and sets it to '127.0.0.1' instead.
This seems like a bug, with no way to set the 'local_hostname' value, and automatically setting it to 'localhost' which is not fully qualified.
Code snippets below:
settings.py
...
EMAIL_HOST = 'smtp-relay.gmail.com'
EMAIL_HOST_USER = "myemail#costumgmail.com"
EMAIL_HOST_PASSWORD = "mypass"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
...
djangotest.py
from django.core.mail import send_mail
send_mail('Django mail', 'This e-mail was sent with Django.', "myemail#costumgmail.com" , ['some.other#mail.com'], fail_silently=False)
# smtplib.SMTPServerDisconnected: Connection unexpectedly closed
smtplibtest.py
from email.message import EmailMessage
import smtplib
email_sender = "myemail#costumgmail.com"
email_password="mypass"
email_reciever ='some.other#mail.com'
subject = "test"
body = "test"
em = EmailMessage()
em['sender'] = email_sender
em['to'] = email_reciever
em['subject'] = subject
em.set_content(body)
smtpObj = smtplib.SMTP('smtp-relay.gmail.com', 587)
smtpObj.ehlo() # (250, b'smtp-relay.gmail.com at your service, [188.26.233.149]\nSIZE 157286400\n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8')
smtpObj.starttls() # (220, b'2.0.0 Ready to start TLS')
smtpObj.login(email_sender, email_password) # (235, b'2.7.0 Accepted')
smtpObj.sendmail(email_sender, email_reciever, em.as_string()) # OK
traceback from django:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/__init__.py", line 87, in send_mail
return mail.send()
File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/message.py", line 298, in send
return self.get_connection(fail_silently).send_messages([self])
File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 124, in send_messages
new_conn_created = self.open()
File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 87, in open
self.connection.starttls(
File "/usr/lib/python3.10/smtplib.py", line 769, in starttls
self.ehlo_or_helo_if_needed()
File "/usr/lib/python3.10/smtplib.py", line 612, in ehlo_or_helo_if_needed
(code, resp) = self.helo()
File "/usr/lib/python3.10/smtplib.py", line 441, in helo
(code, msg) = self.getreply()
File "/usr/lib/python3.10/smtplib.py", line 405, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

(tkinter) ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it

I tried using different ports and find solutions in the internet but I still can't fix it. I tried changing the localhost to 127.0.0.1 and also tried changing the port numbers to all types of values but still won't work. A great help would be greatly appreciated.
import tkinter
import smtplib
import socket
from email.parser import Parser
smtp = smtplib.SMTP
user = ""
password = ""
def connect():
print(msg_entry.get())
smtp = smtplib.SMTP("localhost", 587)
#smtp.login(user,password)
smtp.sendmail(from_entry.get(), to_entry.get(), msg_entry.get())
smtp.quit()
app = tkinter.Tk()
app.title("test")
to_label = tkinter.Label(app,text="To:")
to_entry = tkinter.Entry(app)
from_label = tkinter.Label(app,text="From:")
from_entry = tkinter.Entry(app)
send_button = tkinter.Button(app,text="send",command=connect)
msg_label = tkinter.Label(app,text="Email:")
msg_entry = tkinter.Entry(app,width=50)
#pack(add) the widget to the app.
to_label.pack()
to_entry.pack()
from_label.pack()
from_entry.pack()
msg_label.pack()
msg_entry.pack()
send_button.pack()
#draw the window, have this at the end
app.mainloop()
Whenever I would click the send, I would get the error:
Traceback (most recent call last):
File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:/Users/ADMIN/PycharmProjects/CourseOutcome3/EmailTransmitter-DAMPAC.py", line 15, in connect
smtp = smtplib.SMTP("localhost", 587)
File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\lib\smtplib.py", line 253, in __init__
(code, msg) = self.connect(host, port)
File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\lib\smtplib.py", line 339, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\lib\smtplib.py", line 308, in _get_socket
return socket.create_connection((host, port), timeout,
File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\lib\socket.py", line 808, in create_connection
raise err
File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\lib\socket.py", line 796, in create_connection
sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
You need to have a server on localhost to make it work, i recommend PaperCut, also you may want to check this post of mine about how to create a basic smtp mail server.

Repl.it SMTPLIB OSError: [Errno 99] Cannot assign requested address

I am trying to run simple emailsender.py script on repl.it to send an email.
It works without any problem when I try to run it on desktop PC, but on repl.it I am having an error message OSError: [Errno 99] Cannot assign requested address as detailed below.
The emailsender.py program looks like this:
import smtplib
def send_email(username: str, key: str):
reciever = username+"#theirmail.cz"
sender = "my_email#email.cz"
topic = "Autothorization bot"
# header
msg = "From: %s\r\nSubject: %s\r\nTo: %s\r\n\r\n" % (sender, topic, reciever)
# add message content
content = "Your key is: " + key
msg += content
server = smtplib.SMTP('smtp.seznam.cz')
server.login('my_email#email.cz', "my_email_password")
server.sendmail(sender, reciever, msg)
server.quit()
When I try to run the script via python on repl.it, I get this error message after some time:
>>> import emailsender
>>> emailsender.send_email("username", "test_message")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/runner/botpy/emailsender.py", line 24, in send_email
server = smtplib.SMTP('smtp.seznam.cz')
File "/usr/lib/python3.8/smtplib.py", line 253, in __init__
(code, msg) = self.connect(host, port)
File "/usr/lib/python3.8/smtplib.py", line 337, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "/usr/lib/python3.8/smtplib.py", line 308, in _get_socket
return socket.create_connection((host, port), timeout,
File "/usr/lib/python3.8/socket.py", line 808, in create_connection
raise err
File "/usr/lib/python3.8/socket.py", line 796, in create_connection
sock.connect(sa)
OSError: [Errno 99] Cannot assign requested address
This .py script is a piece of larger discord.py bot that I am trying to host on repl.it, but this should not have any effect, because this script alone is running well individually on desktop PC.
I've tried my best to figure out the cause of this error, but with no success so far.
For reasons unknown to me, a small configuration of commands fixed it.
New part of the script for sending the email looks like this:
server = smtplib.SMTP('smtp.seznam.cz', 587)
server.starttls()
server.ehlo()
server.login('my_email#email.cz', "my_email_password")
server.sendmail(sender, reciever, msg)
server.quit()
I had the same error and
port=587 fixed the problem

How can I fetch emails via IMAP through a Institute proxy in python?

I have already been through these set of solutions for connecting IMAP under proxy
Information to add:
I am trying to write a python code that can fetch mails from gmails IMAP server using imapclient under http,https and socks proxy server of my academic insitute
When tried without any proxy handling, it used to give error
socket.error [101] network is unreachable
import imapclient
import pyzmail
imapObj = imapclient.IMAPClient('imap.gmail.com',ssl=True)
imapObj.login('***********#gmail.com','*********')
imapObj.select_folder('INBOX', readonly=True)
UIDs = imapObj.search(['SINCE 07-Jul-2016'])
for item in UIDs:
rawMessages = imapObj.fetch(item, ['BODY[]', 'FLAGS'])
message = pyzmail.PyzMessage.factory(rawMessages[item]['BODY[]'])
message.get_subject()
message.get_addresses('from')
message.get_addresses('to')
message.get_addresses('cc')
message.get_addresses('bcc')
message.text_part != None
message.text_part.get_payload().decode(message.text_part.charset)
message.html_part != None
message.html_part.get_payload().decode(message.html_part.charset)
imapObj.logout()
However, the process gives error as
File "mailtotext.py", line 16, in <module>
imapObj = imapclient.IMAPClient('imap.gmail.com',ssl=True)
File "/usr/local/lib/python2.7/dist-packages/imapclient/imapclient.py", line 152, in __init__
self._imap = self._create_IMAP4()
File "/usr/local/lib/python2.7/dist-packages/imapclient/imapclient.py",line 164, in _create_IMAP4
self._timeout)
File "/usr/local/lib/python2.7/dist-packages/imapclient/tls.py", line 153, in __init__
imaplib.IMAP4.__init__(self, host, port)
File "/usr/lib/python2.7/imaplib.py", line 172, in __init__
self.open(host, port)
File "/usr/local/lib/python2.7/dist-packages/imapclient/tls.py", line 158, in open
sock = socket.create_connection((host, port), self._timeout)
File "/usr/lib/python2.7/socket.py", line 571, in create_connection
raise err
socket.error: [Errno 101] Network is unreachable
I then followed the above mentioned link procedures owing to my institute proxy as http,https,socks
I have already set my system proxy settings as
http_proxy="http://10.3.100.207:8080/"
https_proxy="https://10.3.100.207:8080/"
ftp_proxy="ftp://10.3.100.207:8080/"
socks_proxy="socks://10.3.100.207:8080/"
and edited the code as
import imapclient
import pyzmail
import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4,"10.3.100.207",8080,True)
socket.socket = socks.socksocket
imapObj = imapclient.IMAPClient('imap.gmail.com',ssl=True)
imapObj.login('***********#gmail.com','*********')
imapObj.select_folder('INBOX', readonly=True)
UIDs = imapObj.search(['SINCE 07-Jul-2016'])
for item in UIDs:
rawMessages = imapObj.fetch(item, ['BODY[]', 'FLAGS'])
message = pyzmail.PyzMessage.factory(rawMessages[item]['BODY[]'])
message.get_subject()
message.get_addresses('from')
message.get_addresses('to')
message.get_addresses('cc')
message.get_addresses('bcc')
message.text_part != None
message.text_part.get_payload().decode(message.text_part.charset)
message.html_part != None
message.html_part.get_payload().decode(message.html_part.charset)
imapObj.logout()
But this process seems to freeze for very long time and finally I always need to make a keyboard interrupt. Its sure that it was freezed somewhere in socket files as per keyboard interrupt output.
Please help me through this, there are hardly solution to such problems over web. I have even tried tunneling but it isn't solving my problem or say making it worse (I might have not implemented it well :P)I would provide any other information and output if needed here

how do i send an email in python?

i've looked online but every time i try to connect to the localhost it says connection refused. Do i need to sign into a valid email address to send email?
Here is my EXACT code.
>>> import smtplib
>>> sender = 'from#fromdomain.com'
#this is my exact sender name bc i don't know if i need to use a valid email address or if i can just make up one since i dont need a password and username
>>> receiver = ['to#todomain.com']
#again, i dont know what to use for the receiver email address
>>> message = 'this is a test'
>>> s = smtplib.SMTP('localhost')
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
s = smtplib.SMTP('localhost')
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py", line 242, in __init__
(code, msg) = self.connect(host, port)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py", line 302, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py", line 277, in _get_socket
return socket.create_connection((port, host), timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 571, in create_connection
raise err
error: [Errno 61] Connection refused
the connection refused error is my problem. i've looked online but i can't figure out how to connect it.
If you want to use gmail to send your message there is some code at: http://www.nixtutor.com/linux/send-mail-through-gmail-with-python/ that you can use. It should be pretty self explaining..
Do you have a smtp server running in your computer? Localhost refers to your own computer.

Categories