I'm currently need to know how to extract a link from html mail in Gmail account.
I able to connect using the python library for gmail provided by google but once i use the fonction describe as example:
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)
return mime_msg
except errors.HttpError, error:
print ('An error occurred: %s') % error
message = GetMimeMessage(service, 'me', '15876d11f0719f43')
#message = GetMessage(service, 'me', '15876d11f0719f43')
#message = str(message)
print (message)
The message looks like this:
style=3D"font-family: Verdana, Geneva, sans-serif; font-siz=
e: 14px; line-height: 20px;"><a href=3D"https://e.vidaxl.com/1/4/1505/1/ZJb=
bJSDLWNxmfpHYIRQzlMiIupCb0wiKMrAxIrfXlymZQ_TK5GUcGAT6rIBJD9nfIFJ5XWG6HnYei-=
G1aQqlfnBxKnJ3yujKlOpRY2UxqroSHS51ofyXzr3kFa7OTyJH5zKbxESXzbTlcQOYxRuEnBcKF=
saVBGQXyJomUGLL6RY" target=3D"_blank" style=3D"color:blue;">SUIVEZ VOTRE CO=
MMANDE</a></td>=0A
As you see at each end it add a "=" sign . I don't know why, is it because i print it ?
My main question is how to extract a specific link from a MIMEmail. I tried lxml withoug success. first because i have those "=" added i think or because it's not a valid html or xml.
Thanks for your help
Related
I am trying to save only a specific part of an email using python. I have the variables service, userId and msg_id but I don't know how to convert the variable plainText to a string in order to take the part that I want in the get_info function
def get_message(service, user_id, msg_id):
try:
#get the message in raw format
message = service.users().messages().get(userId=user_id, id=msg_id, format='raw').execute()
#encode the message in ASCII format
msg_str = base64.urlsafe_b64decode(message['raw'].encode("ASCII")).decode("ASCII")
#put it in an email object
mime_msg = email.message_from_string(msg_str)
#get the plain and html text from the payload
plainText, htmlText = mime_msg.get_payload()
print(get_info(plainText, "start", "finish"))
except Exception as error:
print('An error occurred in the get_message function: %s' % error)
def get_info(plainText, start, end):
usefullText = plainText.split(start)[2]
usefullText = usefullText.split(end)[0]
return usefullText
after running the code I have the following error message:
An error occurred in the get_message function: 'Message' object has no attribute 'split'
Answer:
The method get_payload() doesn't exist for the email.message class. You need to use as_string() instead.
Code Fix:
The code inside your try block needs to be updated, from:
#get the plain and html text from the payload
plainText, htmlText = mime_msg.get_payload()
to:
#get the plain and html text from the payload
plainText, htmlText = mime_msg.as_string()
References:
email.message: Representing an email message — Python 3.8.5 documentation
as_string() method
email.parser: Parsing email messages — Python 3.8.5 documentation
message_from_string() method
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
In my script I need to extract a set of emails that match some query. I decided to use GMail's API python client for this. Now, my understanding was that the GetMimeMessage() was supposed to return a set of decoded base 64 messages. Here is my code:
def GmailInput():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('gmail', 'v1', http=http)
defaultList= ListMessagesMatchingQuery(service, 'me', 'subject:infringement label:unread ')
print(defaultList)
for msg in defaultList:
currentMSG=GetMimeMessage(service, 'me', msg['id'])
....then I parse the text of the emails and extract some things
The problem is, I am unable to actually parse the message body because GetMimeMessage is not returning a base64 decoded message. So what I am actually parsing ends up being completely unreadable by humans.
I find this peculiar because GetMimeMessage (copied below for convenience) literally does a url-safe base 64 decode of the message data. Anyone have any suggestion? Im really stumped on this.
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)
return mime_msg
except errors.HttpError, error:
print ('An error occurred: %s' % error)
You can use User.messages:get. This request requires authorization with at least one of the following scopes.
HTTP request
GET https://www.googleapis.com/gmail/v1/users/userId/messages/id
import base64
import email
from apiclient import errors
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()
print 'Message snippet: %s' % message['snippet']
return message
except errors.HttpError, error:
print 'An error occurred: %s' % error
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)
return mime_msg
except errors.HttpError, error:
print 'An error occurred: %s' % error
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
I'm having some trouble sending a message to multiple addresses using the Gmail API. I've successfully sent a message to only one address, but get the following error when I include multiple comma-separated addresses in the 'To' field:
An error occurred: <HttpError 400 when requesting
https://www.googleapis.com/gmail/v1/users/me/messages/send?alt=json
returned "Invalid to header">
I'm using the CreateMessage and SendMessage methods from this Gmail API guide:
https://developers.google.com/gmail/api/guides/sending
That guide states that the Gmail API requires messages that are RFC-2822 compliant. I again didn't have much luck using some of these addressing examples in the RFC-2822 guide:
https://www.rfc-editor.org/rfc/rfc2822#appendix-A
I'm under the impression that 'mary#x.test, jdoe#example.org, one#y.test' should be a valid string to pass into the 'to' parameter of CreateMessage, but the error that I received from SendMessage leads me to believe otherwise.
Please let me know if you can recreate this problem, or if you have any advice on where I may be making a mistake. Thank you!
Edit: Here is the actual code that yields an error...
def CreateMessage(sender, to, subject, message_text):
message = MIMEText(message_text)
message['to'] = to
message['from'] = sender
message['subject'] = subject
return {'raw': base64.urlsafe_b64encode(message.as_string())}
def SendMessage(service, user_id, message):
try:
message = (service.users().messages().send(userId=user_id, body=message)
.execute())
print 'Message Id: %s' % message['id']
return message
except errors.HttpError, error:
print 'An error occurred: %s' % error
def ComposeEmail():
# build gmail_service object using oauth credentials...
to_addr = 'Mary Smith <mary#x.test>, jdoe#example.org, Who? <60one#y.test>'
from_addr = 'me#address.com'
message = CreateMessage(from_addr,to_addr,'subject text','message body')
message = SendMessage(gmail_service,'me',message)
Getting "Invalid to header" when sending with multiple recipients (comma delimited) in a single header was a regression that was fixed on 2014-08-25.
As James says in its comment, you shouldn't waste time trying to use Gmail API when Python has excellent documented support for using SMTP : email module can compose message including attachements, and smtplib sends them. IMHO you could use Gmail API for what works out of the box but should use the robust modules form Python Standard Library when things go wrong.
It looks like you want to send a text only message : here is a solution adapted from the email module documentation and How to send email in Python via SMTPLIB from Mkyong.com:
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.mime.text import MIMEText
msg = MIMEText('message body')
msg['Subject'] = 'subject text'
msg['From'] = 'me#address.com'
msg['To'] = 'Mary Smith <mary#x.test>, jdoe#example.org, "Who?" <60one#y.test>'
# Send the message via Gmail SMTP server.
gmail_user = 'youruser#gmail.com'
gmail_pwd = 'yourpassword'smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver = smtplib.SMTP('smtp.gmail.com')smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(gmail_user, gmail_pwd)
smtpserver.send_message(msg)
smtpserver.quit()
See also User.drafts reference - error"Invalid to header"
Apparently this bug was recently introduced in Gmail API.