Arresting Flask Mail delivery failure - python

I have the following code that I believed would help me check if email is provided is valid and would be accepted for delivery:
#app.route("/email_send/<email>")
def email_send(email=None):
return_message=None
msg = Message('Online Enquiry', sender='sender#gmail.com', recipients=[email])
msg.body ='We have received your message. We shall be communicating with you'
try:
mail.send(msg)
return_message='SUCCESS'
except Exception as e:
return_message='FAILED'
return json.dumps(str(return_message))
The problem is that it is always returning 'SUCCESS' even when I get address not found in gmail

Related

Django: Send mail to admin on every error raised

I have a project where we process data from various sources. My problem is I want a to send email every time there is an error or error raise my me.
Currently I do something like this where on every raise I send a email. But I want a system where on every error there would be a email sent.
# send an email alert
email_content = "Email content"
subject = "Subject"
if settings.ENVIRONMENT == 'PROD':
BaseScraper.email_alert_for_error(
subject,
email_content,
["admin#mail.com"],
)
else:
BaseScraper.email_alert_for_error(
subject,
email_content,
["admin#mail.com"],
)
You can use try: and except: like such:
try:
<do something>
except Exception as e:
email_content = email_content + e
BaseScraper.email_alert_for_error(
subject,
email_content,
["admin#mail.com"],
)
Here a list of keyword for exception: https://docs.djangoproject.com/en/4.1/ref/exceptions/

Sending emails from my django website, via sendgrid

I want to send account confirmation emails to all the users who sign up on my website, so it has to be an HTML email with the activation link. This is how i am trying to do it:
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
def my_view(request):
current_site = get_current_site(request)
mail_subject = 'Welcome To IIITU Alumni Network'
to_email = email
ctx = {
'user': user,
'domain': current_site.domain,
'uid':urlsafe_base64_encode(force_bytes(user.pk)),
'token':account_activation_token.make_token(user),
}
message = Mail(
to_emails = to_email,
from_email = '<my email address>',
subject = mail_subject,
#I made this html page specifically for sending confirmation email
#I am not sure if this is the correct way to do it
html_content = render_to_string('network/email.html', ctx)
)
try:
#I have this key as an environment variable
sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
#Now this is where the problem is
response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
return HttpResponse("A confirmation Email has been sent to your Institute email address. Please Confirm Your email to complete your registration")
except Exception as e:
print(e.message)
return HttpResponse("The Server seems too busy!! Sorry for the inconvenience. Please try again later, or contact administrator if this problem persists.")
When this particular view is rendered, it throws the following error message:
'UnauthorizedError' object has no attribute 'message'
Since this doesn't send the emails via an SMTP server, according to my understanding i don't need to add anything to my settings.py file(i did add 'sendgrid' to my installed apps after i installed it using pip)Can someone please point out what i did wrong? I have been stuck on this for a while now...
Thank you for your time
I think this line is causing an error.
...
except Exception as e:
print(e.message)
...
Whatever exception is occuring, it doens't have message property.
Two solutions.
print(e)
remove try except block and try to figure out which exception is occurring and then catch that specifically.

Gmail API: message snippet to ignore reply parts of the body

def GetMessage(service, user_id, msg_id):
"""Get a Message with given ID.
Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
msg_id: The ID of the Message required.
Returns:
A Message.
"""
try:
message = service.users().messages().get(userId=user_id, id=msg_id).execute()
return message
except errors.HttpError, error:
print 'An error occurred: %s' % error
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('gmail', 'v1', http=http)
results = service.users().messages().list(userId='me', labelIds='UNREAD').execute()
messages = results.get('messages', [])
for msg in messages:
id = msg['id']
msgobj = GetMessage(service, 'me', id)
print msgobj['snippet']
when you are replying back via gmail, you have your message and then the message from previous replies. The 'snippet' part of message picks up reply as well. I would like to just get the latest text in the email(not the reply part)
yeah that sounds good
On Sun, Feb 21, 2016 at 7:36 PM, <apple#gmail.com> wrote:
you want to play ball? ________________________________________ From: banana#gmail.com
is there anything else besides snippet that gets latest email text?
Nothing much can be done with it, unfortunately. snippet is a short part of the message, which (based on API Explorer observations) usually is around 100+- characters. If the message was too short, it will get the reply part of the preceding message.
What I observed though, is that the message part of the snippet usually has the On [date] statement. I think an approach would be for you to check and split the message if a phrase like that was made (this will be a bit tricky though since the phrase itself can be partial as well).
def GetMimeMessage(service, user_id, msg_id):
"""Get a Message and use it to create a MIME Message.
Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
msg_id: The ID of the Message required.
Returns:
A MIME Message, consisting of data from Message.
"""
try:
message = service.users().messages().get(userId=user_id, id=msg_id,
format='raw').execute()
#print 'Message snippet: %s' % message['snippet']
msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
mime_msg = email.message_from_string(msg_str)
for part in mime_msg.walk():
if part.get_content_type() == 'text/plain':
print part.get_payload()
return mime_msg
except errors.HttpError, error:
print 'An error occurred: %s' % error
I've decided to get Mimemessage instead. This seems to always have the reply part if there is one. This makes it easier to look for it and parse them out

Python Flask Mailchimp signup

I'm trying to use PostMonkey & Flask to HTTP GET an email address (from a from on my website) and then subscribe this to the specified list.
It works and sends the email requesting the user to confirm the subscription, but either server error 500's or when debug mode is on it comes up with
TypeError: signup() takes no arguments (2 given)
Here's my code:
#app.route("/signup", methods=['GET'])
def signup():
try:
email = request.args.get('email')
pm.listSubscribe(id="cdc2ba625c", email_address=email)
except MailChimpException, e:
print e.code
print e.error
return redirect("/")
return signup
I'm not sure what's causing it and it's been bugging me for a while!
If anyone is interested the problem was related to my 'Return' statement, turns out flask doesn't like returning nothing.
#app.route('/signup', methods=['POST'])
def signup():
try:
email = request.form['email']
#email = request.args.get('email')
pm.listSubscribe(id="cdc2ba625c", email_address=email, double_optin=False)
except MailChimpException, e:
print e.code
print e.error
return redirect("/")
return render_template('index.html')
Thanks to all those that commented back

How to refuse a recipient in smtpd.SMTPServer.process_message?

Let's say your processing a message in an overridden class like:
class MailProcessorServer(smtpd.SMTPServer):
def process_message(self, peer, sender, rcpttos, data):
badrecipients = []
for rcpt in rcpttos:
badrecipients.append(rcpt)
#Here I want to warn the sender via a bounced email
# that the recipient does not exist
raise smtplib.SMTPRecipientsRefused(badrecipients)
#but this just crashes the process and eventually the sender times out,
# not good enough
I just want to bounce back to the sender immediately. Instead the sending service (say, GMail) just gives up eventually and warns the user many hours later. The documentation seems pretty sparse.
As documented only in the sources (sorry!), process_message's specs include:
This function should return None, for
a normal `250 Ok' response; otherwise
it returns the desired response string
in RFC 821 format.
So you could "return '554 bad recipients %s' % badrecipients" instead of using that raise statement -- not entirely satisfactory (doesn't properly account for a mix of good and bad, which by RFC 821 should return a '250 Ok' but also send a warning mail later) but it does seem to be the "bounce back immediately" effect that you're looking for with that raise.
The way to reject a message is to return a string with the error code from your process_message method; e.g.
return '550 No such user here'
However, RFC 821 doesn't allow error code 550 to be returned after the message data has been transfered (it should be returned after the RCPT command), and the smtpd module unfortunately doesn't provide an easy way to return an error code at that stage. Furthermore, smtpd.py makes it difficult to subclass its classes by using auto-mangling "private" double-underscore attributes.
You may be able to use the following custom subclasses of smtpd classes, but I haven't tested this code:
class RecipientValidatingSMTPChannel(smtpd.SMTPChannel):
def smtp_RCPT(self, arg):
print >> smtpd.DEBUGSTREAM, '===> RCPT', arg
if not self._SMTPChannel__mailfrom:
self.push('503 Error: need MAIL command')
return
address = self._SMTPChannel__getaddr('TO:', arg)
if not address:
self.push('501 Syntax: RCPT TO: <address>')
return
if self._SMTPChannel__server.is_valid_recipient(address):
self._SMTPChannel__rcpttos.append(address)
print >> smtpd.DEBUGSTREAM, 'recips:', self._SMTPChannel__rcpttos
self.push('250 Ok')
else:
self.push('550 No such user here')
class MailProcessorServer(smtpd.SMTPServer):
def handle_accept(self):
conn, addr = self.accept()
print >> smtpd.DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
channel = RecipientValidatingSMTPChannel(self, conn, addr)
def is_valid_recipient(self, address):
# insert your own tests here, return True if it's valid
return False
The following will discard the mail without bouncing it.
return '554-5.7.1'
Problem: The sender MTA's will try to resend the mail again and again if you reject a mail without bouncing.
Error code 550 will bounce the email which can be a bad idea as you don't want to give a spamer any information concerning your mail server. Be careful with that.
return '550'
Both errors will raise an smtplib.SMTPException. Here is the simplified code I use to handle such exceptions.
try:
if bounce:
return '550 Bad address'
else:
self.send_and_quit(sender, recipients, data)
except smtplib.SMTPException as e:
raise e
except Exception as e:
# Catch any other exception
logging.error(traceback.format_exc())
if not isinstance(e, smtplib.SMTPException):
self.send_and_quit(sender, recipients, data)
else:
raise e

Categories