Giter Club home page Giter Club logo

gmail's Introduction

GMail for Python

A Pythonic interface to Google's GMail, with all the tools you'll need. Search, read and send multipart emails, archive, mark as read/unread, delete emails, and manage labels.

This library is still under development, so please forgive some of the rough edges

Heavily inspired by Kriss "nu7hatch" Kowalik's GMail for Ruby library

Author

Installation

For now, installation is manual (pip support not yet implemented) and the only requirement is to use Python 2 (2.7+ to be precise):

git clone git://github.com/charlierguo/gmail.git

Features

  • Search emails
  • Read emails
  • Emails: label, archive, delete, mark as read/unread/spam, star
  • Manage labels

Basic usage

To start, import the gmail library.

import gmail

Authenticating gmail sessions

To easily get up and running:

import gmail 

g = gmail.login(username, password)

Which will automatically log you into a GMail account. This is actually a shortcut for creating a new Gmail object:

from gmail import Gmail

g = Gmail()
g.login(username, password)
# play with your gmail...
g.logout()

You can also check if you are logged in at any time:

g = gmail.login(username, password)
g.logged_in # Should be True, AuthenticationError if login fails

OAuth authentication

If you have already received an OAuth2 access token from Google for a given user, you can easily log the user in. (Because OAuth 1.0 usage was deprecated in April 2012, this library does not currently support its usage)

gmail = gmail.authenticate(username, access_token)

Filtering emails

Get all messages in your inbox:

g.inbox().mail()

Get messages that fit some criteria:

g.inbox().mail(after=datetime.date(2013, 6, 18), before=datetime.date(2013, 8, 3))
g.inbox().mail(on=datetime.date(2009, 1, 1)
g.inbox().mail(sender="[email protected]") # "from" is reserved, use "fr" or "sender"
g.inbox().mail(to="[email protected]")

Combine flags and options:

g.inbox().mail(unread=True, sender="[email protected]")

Browsing labeled emails is similar to working with your inbox.

g.mailbox('Urgent').mail()

Every message in a conversation/thread will come as a separate message.

g.inbox().mail(unread=True, before=datetime.date(2013, 8, 3) sender="[email protected]")

Working with emails

Important: calls to mail() will return a list of empty email messages (with unique IDs). To work with labels, headers, subjects, and bodies, call fetch() on an individual message. You can call mail with prefetch=True, which will fetch the bodies automatically.

unread = g.inbox().mail(unread=True)
print unread[0].body
# None

unread[0].fetch()
print unread[0].body
# Dear ...,

Mark news past a certain date as read and archive it:

emails = g.inbox().mail(before=datetime.date(2013, 4, 18), sender="[email protected]")
for email in emails:
    email.read() # can also unread(), delete(), spam(), or star()
    email.archive()

Delete all emails from a certain person:

emails = g.inbox().mail(sender="[email protected]")
for email in emails:
    email.delete()

You can use also label method instead of mailbox:

g.label("Faxes").mail()

Add a label to a message:

email.add_label("Faxes")

Download message attachments:

for attachment in email.attachments:
    print 'Saving attachment: ' + attachment.name
    print 'Size: ' + str(attachment.size) + ' KB'
    attachment.save('attachments/' + attachment.name)

There is also few shortcuts to mark messages quickly:

email.read()
email.unread()
email.spam()
email.star()
email.unstar()

Roadmap

Copyright

  • Copyright (c) 2013 Charlie Guo

See LICENSE for details.

gmail's People

Contributors

bhundven avatar carver avatar charlierguo avatar danudey avatar maebert avatar pgwhalen avatar robertf224 avatar thomasrice avatar tonyseek avatar torotoki avatar yanlyub avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gmail's Issues

Error when fetching inbox with no unread emails with unread=True, prefetch=True

When trying to fetch for new emails with .mail(unread=True, prefetch=True) when there's no unread emails, this error is thrown. It does not appear if I don't pass unread or prefetch, but together, it happens.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/gmail/mailbox.py", line 64, in mail
    self.messages.update(self.gmail.fetch_multiple_messages(messages_dict))
  File "/usr/local/lib/python2.7/dist-packages/gmail/gmail.py", line 145, in fetch_multiple_messages
    response, results = self.imap.uid('FETCH', fetch_str, '(BODY.PEEK[] FLAGS X-GM-THRID X-GM-MSGID X-GM-LABELS)')
  File "/usr/lib/python2.7/imaplib.py", line 772, in uid
    typ, dat = self._simple_command(name, command, *args)
  File "/usr/lib/python2.7/imaplib.py", line 1087, in _simple_command
    return self._command_complete(name, self._command(name, *args))
  File "/usr/lib/python2.7/imaplib.py", line 917, in _command_complete
    raise self.error('%s command error: %s %s' % (name, typ, data))
imaplib.error: UID command error: BAD ['Could not parse command']

Sample code:

g = gmail.login("user", "pass")
inbox = g.inbox()
mail = inbox.mail(unread=True, prefetch=True)

I'm not 100% sure if this is a problem on my end/something I'm doing wrong, or on the module's end. Hopefully it is easily fixable!

Retrieve FROM email address of a message

I couldn't find a way to retrieve FROM email address of a message.
After analysing, I just figured out a way to get it. I just parsed the headers dict., split the required string and extracted the email address.

Here is a code snippet that I've added in Message class in message.py :

def get_from_address(self):
authHeader = self.headers["Authentication-Results"]
emailString = authHeader.split(";")[1]
tempList = emailString.split("=")
return tempList[len(tempList)-1]

It works. But its purely a dirty fix, I agree.
Is there any better alternative ?

Email thread handling ?

Hi, how do we work when we have a thread of email from same person which has also been cc to someone.
Can we know the cc person ? Also, does mail.read() reads all the emails in the thread ?

Thanks

Deleting an email accessed via a label search only removes the tag

When an email is accessed as part of a label search, attempting to delete the email only removes the label from the email, but does not delete it.

An example for an email with the tags Inbox and Travel:

for email in g.label('Travel').mail()[0:1]:
    email.fetch()
    process(email.body)
    email.delete

This results in an email that still has the Inbox tag

Error when running the script

Traceback (most recent call last):
File "email.py", line 2, in
import gmail
File "build/bdist.linux-armv6l/egg/gmail/init.py", line 16, in
from .gmail import Gmail
File "build/bdist.linux-armv6l/egg/gmail/gmail.py", line 4, in
File "build/bdist.linux-armv6l/egg/gmail/mailbox.py", line 1, in
"""Read/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes."""
File "build/bdist.linux-armv6l/egg/gmail/message.py", line 2, in
File "/home/pi/AirConRemote/email.py", line 8, in
g = gmail.login(username, password)
AttributeError: 'module' object has no attribute 'login'

Note: The 'username' and 'password' have been hidden for security reasons.
However it works by using python in command line.

Documentation on Message Components (sender, to, content-transfer encoding, etc)

Three questions all of which are related to how the data is returned once fetched.

  1. Is there some documentation on the different pieces of information retrieved with the message? I'm looking to return the body of the message .body, who sent it, content-transfer encoding, etc. I'm using some google aliases and want to separate things out and need both the message and the sender returned.

  2. Along the same lines, could the object returned be simplified into a dict? That would make driving through the data a little easier although potentially cumbersome if you pull a large number of emails.

  3. You might consider adding some base64 code to decode the message. If you return a dict and see the content-transfer-encoding = 64 you could call the following type of "fix" for the text.

Example:
Content-Transfer-Encoding: base64
text=base64.decodestring(messages[0].body)

Great project!

Gmail prevented login with `modern security standards` message

I attempted logging in from my terminal/Ipython and got this message:

Sign-in attempt prevented ... Someone just tried to sign in to your Google Account [email protected] from an app that doesn't meet modern security standards.

Seem like I probably need to update a package used for authenticating, but not sure what exactly. Any suggestions?

Couldn't hande attachments in uuencode format

If there is a mail with attachment in uuencode format in my mailbox, the gmail message shows that there is not attachment and returns body with uuencoded attachment in it.
Could you please fix it?

Is development still ongoing ?

This is an excellent module and I'd like to base some work on it to create a client, but is the development still ongoing ?

Dependencies?

What are the dependencies required for the package to work? Consider adding a requirements.txt file?

Add sending mail feature

This module is very useful for me, but this version of module does not support to send mail.

Another module is needed to send mail via google SMTP, so sending mail function is needed in this module.

Detecting empty sets

I decided to write a little email filter to run on my vps and I ran into an interesting problem:

Traceback (most recent call last):
File "mailfilter.py", line 19, in
mail.read()
File "/usr/local/lib/python2.7/dist-packages/gmail-0.0.5-py2.7.egg/gmail/message.py", line 41, in read
self.gmail.imap.uid('STORE', self.uid, '+FLAGS', flag)
File "/usr/lib/python2.7/imaplib.py", line 760, in uid
typ, dat = self._simple_command(name, command, *args)
File "/usr/lib/python2.7/imaplib.py", line 1070, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "/usr/lib/python2.7/imaplib.py", line 905, in _command_complete
raise self.error('%s command error: %s %s' % (name, typ, data))
imaplib.error: UID command error: BAD ['Could not parse command']

https://gist.github.com/anonymous/bd96cbcd768ce9c2647d
This is my code.

The problem seems to be that after running the filter once, it works as expected. The unwanted behaviour pops up if you run it multiple times if there are no items left matching the criteria, instead of holding 0 or None emails contains 1 message object, which I checked many times against my actual gmail account is not there. This falls automatically through the len() check and causes problems if you start calling methods on this "fake" message object. With message_id = None and no uid.

html parsing

Is there a way to avoid the parse of the html in the body? I would like to retrieve the raw message instead. Since it's bad parsed due to outlook strange html tags.

UnicodeDecodeError in fetch

    mail.fetch()
  File "build/bdist.linux-x86_64/egg/gmail/message.py", line 181, in fetch
  File "build/bdist.linux-x86_64/egg/gmail/message.py", line 147, in parse
  File "build/bdist.linux-x86_64/egg/gmail/message.py", line 134, in parse_subject
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 30: ordinal not in range(128)

Bug in attachment handling

Attachment handling forces the application to exit with the following error:

  File "lib/gmail/gmail/message.py", line 171, in fetch
    self.parse(results[0])
  File "lib/gmail/gmail/message.py", line 164, in parse
    self.attachments = [Attachment(attachment) for attachment in self.message._payload if attachment.get('Content-Disposition') is not None]
AttributeError: 'str' object has no attribute 'get'

Intermittent AuthenticationErrors when authenticating with an OAuth2 token

I'm using the gmail library as part of an application that gets run regularly (every couple of minutes) through cron. Every once in a while (once every couple of hours), I see something like this in the cron logs:

Traceback (most recent call last):
  File "/home/misha/git/supersaas2google/check.py", line 86, in <module>
    main()
  File "/home/misha/git/supersaas2google/check.py", line 73, in main
    g = gmail.authenticate(USERNAME, credentials.access_token)
  File "/usr/local/lib/python2.7/dist-packages/gmail-0.0.5-py2.7.egg/gmail/utils.py", line 12, in authenticate
    gmail.authenticate(username, access_token)
  File "/usr/local/lib/python2.7/dist-packages/gmail-0.0.5-py2.7.egg/gmail/gmail.py", line 121, in authenticate
    raise AuthenticationError
gmail.exceptions.AuthenticationError

I don't understand why it fails only some of the time, but works for the rest of the time.

Do you have any ideas about what the problem could be?

How to separate attachement from message

I want to list messages and their attachments and then (if I want to) to download attachement. Now on command email.fetch() I download everything.
Can I separate them?

current_mailbox introduces a state problem

When I was adding the fetch_thread() functionally which uses several mailboxes in one function, I noticed that you must take good care of which is "current." This is confusing to work with and could introduce some mysterious bugs. I'll look into refactoring things so that all functions that require a mailbox to work explicitly take that as an arg. If anyone sees anything wrong with this idea, speak up.

Authentication error

AuthenticationError                       Traceback (most recent call last)
<ipython-input-3-69ade5292074> in <module>()
----> 1 g.login ('**********', '**********')

/home/debdut/Code/workspace/gmail/gmail/gmail.pyc in login(self, username, password)
    104                 self.fetch_mailboxes()
    105         except imaplib.IMAP4.error:
--> 106             raise AuthenticationError
    107 
    108 

AuthenticationError: 

I also got an email that Google is blocking the login. How to fix it?
Note: I have replaced my username password with *'s.

error during fetch()

I'm getting this error when trying to fetch any msg. I'm at commit 667c149 and using ubuntu. Looks like a bug. Hopefully Charlie can fix it soon.

unread[1].fetch()
Traceback (most recent call last):
File "", line 1, in
File "message.py", line 171, in fetch
self.parse(results[0])
File "message.py", line 164, in parse
self.attachments = [Attachment(attachment) for attachment in self.message._payload if attachment.get('Content-Disposition') is not None]
AttributeError: 'str' object has no attribute 'get'

Add expunge

Please add the expunge function to allow permanent removal of messages in the trash

Nothing returned at all in email

Here is what is some of the output

['body', 'delivered_to', 'fr', 'uid', 'thread', 'thread_id', 'cc', 'labels', 'mailbox', 'to', 'flags', 'sent_at', 'message', 'subject', 'message_id', 'gmail']
[None, None, None, '161464', [], None, None, [], <gmail.mailbox.Mailbox instance at 0x1049179e0>, None, [], None, None, None, None, <gmail.gmail.Gmail instance at 0x1049173b0>]
<gmail.message.Message instance at 0x10492ee60>

Here is the code I am using... I dont think I am doing anything wrong. logged_in is returning true so it appears I am authenticated.

!/usr/bin/python

from gmail import Gmail
import datetime

g = Gmail()

g.login("noybusername","noybpassword")
emails = g.inbox().mail(fr="[email protected]")
print(g.logged_in)
print(emails[0].uid)
print(emails[0].fr)
for email in emails:
print(email.dict.keys())
print(email.dict.values())
print(email)

g.logout()

How to retrieve mail read/unread status ?

I am trying to retrieve read/unread status of mail using
emails[0].is_read.
It returns ">" for all emails whether its read or unread.

Also tried with emails[0].read. But it also returns ">".

Please help

Fetching Unread Emails removes Inbox label

unread = g.inbox().mail(unread=True)
print unread[0].body

This works once, but after that the email moves all the emails to All Mails from Inbox and the list becomes empty.

Export Lower API for custom search email

Gmail support "Search X-GM-RAW ..." command, which we can use
gmail.imap.uid('SEARCH', 'X-GM-RAW', .....) to fetch email;

but I need the result to be wrapped as the Message object.

Which means, separate the Mailbox.mail function into fetching part and wrapping part.

Get Date, Sender info from a message

Hello,
How is it possible to get the sender Info to a string in format Some Name <[email protected]>, the date it was sent and if there any other recipients (cc)? I tried the following but it din't worked:

inbox = g.inbox().mail(sender="[email protected]")
for msg in inbox:
                    msg.fetch()
                    print msg.body, msg.subject, msg.date, msg.cc

Using gmail inside a with

Something like this

class Gmail:

    def __init__(self, username, password):
        self.username = username
        self.password = password

    def __enter__(self):
        # note: getpass might be better here, instead of keeping the pwd in memory
        self.g = gmail.login(self.username, self.password)
        return self.g

    def __exit__(self, *args, **kwds):
        try:
            print('logging out...')
            self.g.logout()
        except:
            raise

allows this

with Gmail(username, password) as conn:
    print('Reading all your emails from spam folder:')

    spam_box = conn.spam().mail(prefetch=True)
    n = conn.spam().count()

    for idx, email in enumerate(spam_box):
        print('fetching %d of %d...' % (idx + 1, n))

which would be nice to have implemented in the gmail package

Message instance has no attribute 'body'

I'm trying to fetch the body of an email using

mails = g.inbox().mail(sender="[email protected]")
mail = mails[0].fetch()
print mail['subject']
print mail.body

Here, I am able to get properties like subject, Received, etc. but when printing body, I get this error :

Message instance has no attribute 'body'

This is the data I'm getting :

From nobody Mon Dec 26 16:42:46 2016
Delivered-To: [email protected]
Received: by 10.28.211.66 with SMTP id ferf98er9fef9fr;
.
.
.
X-Source-Dir: erferfefefrref:/public_html
X-CMAE-Envelope: grtgrtgrtgrtgrt......

This is the message body

Bug: "object of type 'NoneType' has no len()" in mail.fetch()

Hi

I have a script that fetches my emails (more than 5000) and there is an issue with a specific email (maybe also with some others ?). Sorry I can only give you the error and not the content of the email because I don't know which one it is...

Traceback (most recent call last):
File "get_emails_gmail.py", line 54, in
mail.fetch()
File "build\bdist.win-amd64\egg\gmail\message.py", line 181, in fetch
self.parse(results[0])
File "build\bdist.win-amd64\egg\gmail\message.py", line 173, in parse
if not isinstance(attachment, basestring) and attachment.get('Content-Disposition') is not None
File "build\bdist.win-amd64\egg\gmail\message.py", line 223, in init
self.size = int(round(len(self.payload)/1000.0))
TypeError: object of type 'NoneType' has no len()

email.spam() doesn't work???

email.star()
email.read()
email.unstar()
.. all the other work
except email.spam()

AttributeError: Message instance has no attribute 'spam'

filtering by more than one email

in gmail contacts, a person can have more than one email, some of my contacts have 3 emails, but they are the same person. How do I filter by all three of those email? I can link to gmail contacts to retrieve the 3 emails, but then what?

Or maybe can it be integrated with gmail contacts, so i can filter by a specific contact. That would be really useful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.