2008-12-08 2 views
82

Как подключиться к Gmail и определить, какие сообщения имеют вложения? Затем я хочу загрузить каждое вложение, распечатывая Subject: и From: для каждого сообщения при его обработке.Как загрузить все письма с вложениями из Gmail?

+24

Этот сайт посвящен получению четко определенных ответов на четко определенные вопросы. Является ли мой вопрос непонятным? Теперь я ищу четко определенный ответ на одном из трех языков, которые я обычно использую. – 2009-03-14 16:59:40

ответ

147

Hard один :-)

import email, getpass, imaplib, os 

detach_dir = '.' # directory where to save attachments (default: current) 
user = raw_input("Enter your GMail username:") 
pwd = getpass.getpass("Enter your password: ") 

# connecting to the gmail imap server 
m = imaplib.IMAP4_SSL("imap.gmail.com") 
m.login(user,pwd) 
m.select("[Gmail]/All Mail") # here you a can choose a mail box like INBOX instead 
# use m.list() to get all the mailboxes 

resp, items = m.search(None, "ALL") # you could filter using the IMAP rules here (check http://www.example-code.com/csharp/imap-search-critera.asp) 
items = items[0].split() # getting the mails id 

for emailid in items: 
    resp, data = m.fetch(emailid, "(RFC822)") # fetching the mail, "`(RFC822)`" means "get the whole stuff", but you can ask for headers only, etc 
    email_body = data[0][1] # getting the mail content 
    mail = email.message_from_string(email_body) # parsing the mail content to get a mail object 

    #Check if any attachments at all 
    if mail.get_content_maintype() != 'multipart': 
     continue 

    print "["+mail["From"]+"] :" + mail["Subject"] 

    # we use walk to create a generator so we can iterate on the parts and forget about the recursive headach 
    for part in mail.walk(): 
     # multipart are just containers, so we skip them 
     if part.get_content_maintype() == 'multipart': 
      continue 

     # is this part an attachment ? 
     if part.get('Content-Disposition') is None: 
      continue 

     filename = part.get_filename() 
     counter = 1 

     # if there is no filename, we create one with a counter to avoid duplicates 
     if not filename: 
      filename = 'part-%03d%s' % (counter, 'bin') 
      counter += 1 

     att_path = os.path.join(detach_dir, filename) 

     #Check if its already there 
     if not os.path.isfile(att_path) : 
      # finally write the stuff 
      fp = open(att_path, 'wb') 
      fp.write(part.get_payload(decode=True)) 
      fp.close() 

Wowww! Это было что-то.;-) Но попробуйте то же самое в Java, просто для удовольствия!

Кстати, я проверил это в оболочке, поэтому некоторые ошибки, вероятно, останутся.

Наслаждайтесь

EDIT:

Поскольку имена почтового ящика могут меняться от одной страны в другую, я рекомендую делать m.list() и выбрать пункт в нем, прежде чем m.select("the mailbox name"), чтобы избежать этой ошибки:

imaplib.error: command SEARCH illegal in state AUTH, only allowed in states SELECTED

+1

Это потрясающе, ребята! Отлично сработано! : D: D – 2009-03-16 19:08:17

+0

Спасибо J.F. Написал, что wuick и грязный, вы дали ему значение :-D – 2009-03-18 16:19:32

9

Я не специалист по Perl, но я знаю, что GMail поддерживает протоколы IMAP и POP3, 2, которые являются полностью стандартными и позволяют вам это делать.

Возможно, это поможет вам начать работу.

+0

IMAP Я бы сказал, что он более надежный из двух для резервного копирования. – 2008-12-08 04:32:50

4

Внутри gmail вы можете фильтровать на «имеет: вложение», использовать его для идентификации сообщений, которые вы должны получать при тестировании. Обратите внимание, что это означает, что оба сообщения со вложенными файлами (значок скрепки показан), а также встроенные вложенные изображения (без скрепки).

API-интерфейс Gmail отсутствует, поэтому IMAP или POP являются вашими реальными вариантами. JavaMail API может оказать некоторую помощь, а также эту очень краткую статью по адресу downloading attachments from IMAP using Perl. Некоторые previous questions здесь, на SO, также могут помочь.

Этот PHP example может помочь. К сожалению, из того, что я вижу, в файле imap_header нет информации о вложениях, поэтому загрузка тела требуется, чтобы увидеть поле X-Attachment-Id. (кто-то, пожалуйста, докажите мне неправду).

1

Поскольку Gmail поддерживает стандартные протоколы POP и IMAP, любая платформа, инструмент, приложение, компонент или API, который обеспечивает клиентскую сторону любого из протоколов, должен работать.

Я предлагаю выполнить поиск Google для вашего любимого языка/платформы (например, «python»), плюс «поп», плюс «imap», плюс, возможно, «с открытым исходным кодом», плюс, возможно, «загрузить» или «просмотреть», , и посмотреть, что вы получаете для опций.

Существует множество бесплатных приложений и компонентов, выберите несколько, которые кажутся достойными, проверьте отзывы, а затем загрузите и наслаждайтесь.

1

Вы должны знать, что для подключения к GMail (как для POP3, так и для IMAP - это, конечно, верно и для SMTP-серверов, кроме порта 25, но это еще одна история).

0

Вы ознакомились с GMail 3rd party add-ons по wikipedia?

В частности, PhpGmailDrive - это приложение с открытым исходным кодом, которое вы можете использовать как есть, или, возможно, учиться на вдохновение?

8
#!/usr/bin/env python 
"""Save all attachments for given gmail account.""" 
import os, sys 
from libgmail import GmailAccount 

ga = GmailAccount("[email protected]", "pA$$w0Rd_") 
ga.login() 

# folders: inbox, starred, all, drafts, sent, spam 
for thread in ga.getMessagesByFolder('all', allPages=True): 
    for msg in thread: 
     sys.stdout.write('.') 
     if msg.attachments: 
      print "\n", msg.id, msg.number, msg.subject, msg.sender 
      for att in msg.attachments: 
       if att.filename and att.content: 
        attdir = os.path.join(thread.id, msg.id) 
        if not os.path.isdir(attdir): 
        os.makedirs(attdir)     
        with open(os.path.join(attdir, att.filename), 'wb') as f: 
         f.write(att.content) 

непроверенных

  1. Убедитесь, что TOS позволяет такие сценарии в противном случае ваш аккаунт будет приостановлен
  2. Там может быть лучше варианты: GMail автономный режим, Thunderbird + ExtractExtensions, GmailFS, Gmail Drive и т.д.
+1

http://libgmail.cvs.sourceforge.net/viewvc/libgmail/libgmail/libgmail.py?view=markup – jfs 2009-03-19 05:40:01

0

Для Java вы найдете G4J. Это набор API-интерфейсов для связи с Google Mail с помощью Java (скриншот на домашней странице клиента демонстрация электронной почты построена вокруг этого)

7

Взгляните на Mail::Webmail::Gmail:

ПОЛУЧЕНИЕ ATTACHMENTS

Там два способа, чтобы получить вложение:

1 -> Отправляя ссылку на определенное приложение возвращенного get_indv_email

# Creates an array of references to every attachment in your account 
my $messages = $gmail->get_messages(); 
my @attachments; 

foreach (@{ $messages }) { 
    my $email = $gmail->get_indv_email(msg => $_); 
    if (defined($email->{ $_->{ 'id' } }->{ 'attachments' })) { 
     foreach (@{ $email->{ $_->{ 'id' } }->{ 'attachments' } }) { 
      push(@attachments, $gmail->get_attachment(attachment => $_)); 
      if ($gmail->error()) { 
       print $gmail->error_msg(); 
      } 
     } 
    } 
} 

2 -> Или, посылая ID и идентификатор вложений

#retrieve specific attachment 
my $msgid = 'F000000000'; 
my $attachid = '0.1'; 
my $attach_ref = $gmail->get_attachment(attid => $attachid, msgid => $msgid); 

(Возвращает ссылку на скаляр, который содержит данные из приложения.)

1

Вот что я написал для загрузки своих банковских выписок в Groovy (динамический язык для платформы Java).

import javax.mail.* 
import java.util.Properties 

String gmailServer 
int gmailPort 
def user, password, LIMIT 
def inboxFolder, root, StartDate, EndDate 


// Downloads all attachments from a gmail mail box as per some criteria 
// to a specific folder 
// Based on code from 
// http://agileice.blogspot.com/2008/10/using-groovy-to-connect-to-gmail.html 
// http://stackoverflow.com/questions/155504/download-mail-attachment-with-java 
// 
// Requires: 
//  java mail jars in the class path (mail.jar and activation.jar) 
//  openssl, with gmail certificate added to java keystore (see agileice blog) 
//   
// further improvement: maybe findAll could be used to filter messages 
// subject could be added as another criteria 
////////////////////// <CONFIGURATION> ////////////////////// 
// Maximm number of emails to access in case parameter range is too high 
LIMIT = 10000 

// gmail credentials 
gmailServer = "imap.gmail.com" 
gmailPort = 993 

user = "[email protected]" 
password = "gmailpassword" 

// gmail label, or "INBOX" for inbox 
inboxFolder = "finance" 

// local file system where the attachment files need to be stored 
root = "D:\\AttachmentStore" 

// date range dd-mm-yyyy 
StartDate= "31-12-2009" 
EndDate = "1-6-2010" 
////////////////////// </CONFIGURATION> ////////////////////// 

StartDate = Date.parse("dd-MM-yyyy", StartDate) 
EndDate = Date.parse("dd-MM-yyyy", EndDate) 

Properties props = new Properties(); 
props.setProperty("mail.store.protocol", "imaps"); 
props.setProperty("mail.imaps.host", gmailServer); 
props.setProperty("mail.imaps.port", gmailPort.toString()); 
props.setProperty("mail.imaps.partialfetch", "false"); 

def session = javax.mail.Session.getDefaultInstance(props,null) 
def store = session.getStore("imaps") 

store.connect(gmailServer, user, password) 

int i = 0; 
def folder = store.getFolder(inboxFolder) 

folder.open(Folder.READ_ONLY) 

for(def msg : folder.messages) { 

    //if (msg.subject?.contains("bank Statement")) 
    println "[$i] From: ${msg.from} Subject: ${msg.subject} -- Received: ${msg.receivedDate}" 

    if (msg.receivedDate < StartDate || msg.receivedDate > EndDate) { 
     println "Ignoring due to date range" 
     continue 
    } 


    if (msg.content instanceof Multipart) { 
     Multipart mp = (Multipart)msg.content; 

     for (int j=0; j < mp.count; j++) { 

      Part part = mp.getBodyPart(j); 

      println " ---- ${part.fileName} ---- ${part.disposition}" 

      if (part.disposition?.equalsIgnoreCase(Part.ATTACHMENT)) { 

       if (part.content) { 

        def name = msg.receivedDate.format("yyyy_MM_dd") + " " + part.fileName 
        println "Saving file to $name" 

        def f = new File(root, name) 

        //f << part.content 
        try { 
         if (!f.exists()) 
          f << part.content 
        } 
        catch (Exception e) { 
         println "*** Error *** $e" 
        } 
       } 
       else { 
        println "NO Content Found!!" 
       } 
      } 
     } 
    } 

    if (i++ > LIMIT) 
     break; 

} 
3

Если какой-либо из вас обновлен до питона 3.3 Я взял 2.7 скрипт из HERE и обновил его до 3.3. Также исправлены некоторые проблемы с тем, как gmail возвращал информацию.

# Something in lines of http://stackoverflow.com/questions/348630/how-can-i-download-all-emails-with-attachments-from-gmail 
# Make sure you have IMAP enabled in your gmail settings. 
# Right now it won't download same file name twice even if their contents are different. 
# Gmail as of now returns in bytes but just in case they go back to string this line is left here. 

import email 
import getpass, imaplib 
import os 
import sys 
import time 

detach_dir = '.' 
if 'attachments' not in os.listdir(detach_dir): 
    os.mkdir('attachments') 

userName = input('Enter your GMail username:\n') 
passwd = getpass.getpass('Enter your password:\n') 


try: 
    imapSession = imaplib.IMAP4_SSL('imap.gmail.com',993) 
    typ, accountDetails = imapSession.login(userName, passwd) 
    if typ != 'OK': 
     print ('Not able to sign in!') 
     raise 

    imapSession.select('Inbox') 
    typ, data = imapSession.search(None, 'ALL') 
    if typ != 'OK': 
     print ('Error searching Inbox.') 
     raise 

    # Iterating over all emails 
    for msgId in data[0].split(): 
     typ, messageParts = imapSession.fetch(msgId, '(RFC822)') 

     if typ != 'OK': 
      print ('Error fetching mail.') 
      raise 

     #print(type(emailBody)) 
     emailBody = messageParts[0][1] 
     #mail = email.message_from_string(emailBody) 
     mail = email.message_from_bytes(emailBody) 

     for part in mail.walk(): 
      #print (part) 
      if part.get_content_maintype() == 'multipart': 
       # print part.as_string() 
       continue 
      if part.get('Content-Disposition') is None: 
       # print part.as_string() 
       continue 

      fileName = part.get_filename() 

      if bool(fileName): 
       filePath = os.path.join(detach_dir, 'attachments', fileName) 
       if not os.path.isfile(filePath) : 
        print (fileName) 
        fp = open(filePath, 'wb') 
        fp.write(part.get_payload(decode=True)) 
        fp.close() 

    imapSession.close() 
    imapSession.logout() 

except : 
    print ('Not able to download all attachments.') 
    time.sleep(3) 
2
/*based on http://www.codejava.net/java-ee/javamail/using-javamail-for-searching-e-mail-messages*/ 
package getMailsWithAtt; 

import java.io.File; 
import java.io.IOException; 
import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.Properties; 

import javax.mail.Address; 
import javax.mail.Folder; 
import javax.mail.Message; 
import javax.mail.MessagingException; 
import javax.mail.Multipart; 
import javax.mail.NoSuchProviderException; 
import javax.mail.Part; 
import javax.mail.Session; 
import javax.mail.Store; 
import javax.mail.internet.MimeBodyPart; 
import javax.mail.search.AndTerm; 
import javax.mail.search.SearchTerm; 
import javax.mail.search.ReceivedDateTerm; 
import javax.mail.search.ComparisonTerm; 

public class EmailReader { 
    private String saveDirectory; 

    /** 
    * Sets the directory where attached files will be stored. 
    * 
    * @param dir 
    *   absolute path of the directory 
    */ 
    public void setSaveDirectory(String dir) { 
     this.saveDirectory = dir; 
    } 

    /** 
    * Downloads new messages and saves attachments to disk if any. 
    * 
    * @param host 
    * @param port 
    * @param userName 
    * @param password 
    * @throws IOException 
    */ 
    public void downloadEmailAttachments(String host, String port, 
      String userName, String password, Date startDate, Date endDate) { 
     Properties props = System.getProperties(); 
     props.setProperty("mail.store.protocol", "imaps"); 
     try { 
      Session session = Session.getDefaultInstance(props, null); 
      Store store = session.getStore("imaps"); 
      store.connect("imap.gmail.com", userName, password); 
      // ... 
      Folder inbox = store.getFolder("INBOX"); 
      inbox.open(Folder.READ_ONLY); 
      SearchTerm olderThan = new ReceivedDateTerm (ComparisonTerm.LT, startDate); 
      SearchTerm newerThan = new ReceivedDateTerm (ComparisonTerm.GT, endDate); 
      SearchTerm andTerm = new AndTerm(olderThan, newerThan); 
      //Message[] arrayMessages = inbox.getMessages(); <--get all messages 
      Message[] arrayMessages = inbox.search(andTerm); 
      for (int i = arrayMessages.length; i > 0; i--) { //from newer to older 
       Message msg = arrayMessages[i-1]; 
       Address[] fromAddress = msg.getFrom(); 
       String from = fromAddress[0].toString(); 
       String subject = msg.getSubject(); 
       String sentDate = msg.getSentDate().toString(); 
       String receivedDate = msg.getReceivedDate().toString(); 

       String contentType = msg.getContentType(); 
       String messageContent = ""; 

       // store attachment file name, separated by comma 
       String attachFiles = ""; 

       if (contentType.contains("multipart")) { 
        // content may contain attachments 
        Multipart multiPart = (Multipart) msg.getContent(); 
        int numberOfParts = multiPart.getCount(); 
        for (int partCount = 0; partCount < numberOfParts; partCount++) { 
         MimeBodyPart part = (MimeBodyPart) multiPart 
           .getBodyPart(partCount); 
         if (Part.ATTACHMENT.equalsIgnoreCase(part 
           .getDisposition())) { 
          // this part is attachment 
          String fileName = part.getFileName(); 
          attachFiles += fileName + ", "; 
          part.saveFile(saveDirectory + File.separator + fileName); 
         } else { 
          // this part may be the message content 
          messageContent = part.getContent().toString(); 
         } 
        } 
        if (attachFiles.length() > 1) { 
         attachFiles = attachFiles.substring(0, 
           attachFiles.length() - 2); 
        } 
       } else if (contentType.contains("text/plain") 
         || contentType.contains("text/html")) { 
        Object content = msg.getContent(); 
        if (content != null) { 
         messageContent = content.toString(); 
        } 
       } 

       // print out details of each message 
       System.out.println("Message #" + (i + 1) + ":"); 
       System.out.println("\t From: " + from); 
       System.out.println("\t Subject: " + subject); 
       System.out.println("\t Received: " + sentDate); 
       System.out.println("\t Message: " + messageContent); 
       System.out.println("\t Attachments: " + attachFiles); 
      } 

      // disconnect 
      inbox.close(false); 
      store.close(); 

     } catch (NoSuchProviderException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } catch (MessagingException e) { 
      e.printStackTrace(); 
      System.exit(2); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    } 

    /** 
    * Runs this program with Gmail POP3 server 
    * @throws ParseException 
    */ 
    public static void main(String[] args) throws ParseException { 
     String host = "pop.gmail.com"; 
     String port = "995"; 
     String userName = "[email protected]"; 
     String password = "pass"; 
     Date startDate = new SimpleDateFormat("yyyy-MM-dd").parse("2014-06-30"); 
     Date endDate = new SimpleDateFormat("yyyy-MM-dd").parse("2014-06-01"); 
     String saveDirectory = "C:\\Temp"; 

     EmailReader receiver = new EmailReader(); 
     receiver.setSaveDirectory(saveDirectory); 
     receiver.downloadEmailAttachments(host, port, userName, password,startDate,endDate); 

    } 
} 

Maven зависимости:

<dependency> 
    <groupId>com.sun.mail</groupId> 
    <artifactId>javax.mail</artifactId> 
    <version>1.5.1</version> 
</dependency> 
3

Вопрос довольно старые и в то время Gmail API не была доступна. Но теперь Google предоставляет API Gmail для доступа к IMAP. См. API Gmail Google here. Также см. google-api-python-client на pypi.

Смежные вопросы