Gmail에서 첨부 파일이있는 모든 이메일을 다운로드하려면 어떻게해야합니까?


83

Gmail에 연결하고 첨부 파일이있는 메시지를 확인하려면 어떻게합니까? 그런 다음 각 첨부 파일을 다운로드하여 처리 할 때 각 메시지에 대해 제목 : 및 보낸 사람 :을 인쇄하고 싶습니다.


24
이 사이트는 잘 정의 된 질문에 대해 잘 정의 된 답변을 얻는 것에 관한 것입니다. 내 질문이 잘 정의되어 있지 않습니까? 이제 저는 제가 일반적으로 사용하는 3 개 언어 중 하나로 잘 정의 된 답변을 찾고 있습니다.

답변:


154

어려운 것 :-)

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()

와우! 그것은 무언가였습니다. ;-) 그러나 재미를 위해 자바에서도 똑같이 시도하십시오!

그건 그렇고, 쉘에서 테스트했기 때문에 약간의 오류가 남아있을 수 있습니다.

즐겨

편집하다:

사서함 이름은 한 국가에서 다른 국가로 변경 될 수 있기 때문에이 오류를 방지하기 위해 m.list()전에 항목을 선택하는 것이 좋습니다 m.select("the mailbox name").

imaplib.error : SEARCH 명령이 AUTH 상태에서 잘못되었습니다. SELECTED 상태에서만 허용됩니다.


감사합니다 JF은 당신이 D는 가치를주고, 그 wuick 더러운 쓴
전자 satis

이것은 좋은 대답입니다. 큰 첨부 파일에서 malloc 오류와 함께 죽습니다. Python (57780) malloc : *** mmap (size = 9658368)

스크립트의 어디에서 죽습니까? 이 오류는 나타나지 않지만 해결 방법을 찾을 수 있습니다.
e-satis

imaplib.py lib : (*** 오류 : 지역을 할당 할 수 없음) error resp, data = m.fetch (emailid, "(RFC822)") # 메일 파일 가져 오기 "/Library/Frameworks/Python.framework/Versions /2.5/lib/python2.5/imaplib.py ", 437 행, in fetch typ, dat = self._simple_command (name, message_set, message_parts)

고도로 활동적인 시스템에서 이것을 실행해야한다면 모든 이메일을 개별적으로 처리하는 것이 좋을까요, 아니면 주기적으로 한 번에 모두 처리하는 것이 좋을까요? 두 솔루션 모두 대기열이 필요하지만 어느 것이 더 쉽게 확장 할 수 있는지 궁금합니다.
kari.patila

9

저는 Perl에 대한 전문가는 아니지만 Gmail은 완전히 표준 인 2 개의 프로토콜 인 IMAP 및 POP3를 지원하며이를 수행 할 수 있습니다.

시작하는 데 도움이 될 수 있습니다.


IMAP 백업 목적으로 둘 중 더 신뢰할 수 있다고 말하고 싶습니다.
Kris Kumler

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

ga = GmailAccount("your.account@gmail.com", "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 드라이브 등.


7

Mail :: Webmail :: Gmail을 살펴보십시오 .

첨부 파일 받기

첨부 파일을 얻는 방법에는 두 가지가 있습니다.

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 및 메시지 ID를 전송하여

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

(첨부 파일의 데이터를 보유하는 스칼라에 대한 참조를 반환합니다.)


4

Gmail 내에서 "has : attachment"를 필터링하고이를 사용하여 테스트 할 때 받아야하는 메시지를 식별 할 수 있습니다. 파일이 첨부 된 메시지 (종이 클립 아이콘이 표시됨)와 인라인 첨부 이미지 (종이 클립이 표시되지 않음)를 모두 제공하는 것으로 보입니다.

Gmail API가 없으므로 IMAP 또는 POP가 유일한 실제 옵션입니다. JavaMail API는 일부 지원뿐만 아니라에서이 매우 간결한 글이 될 수 있습니다 펄을 사용하여 IMAP에서 다운로드 첨부 . 일부 이전 질문 SO에 여기 수도도 도움이됩니다.

PHP 예제 도 도움 이 될 수 있습니다. 아쉽게도 imap_header에 첨부 파일 정보가 포함되어 있지 않으므로 X-Attachment-Id 필드를 보려면 본문을 다운로드해야합니다. (누군가 나를 틀렸다는 것을 증명하십시오).


3

Python 3.3으로 업데이트 한 사람이 있다면 여기 에서 2.7 스크립트를 가져와 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 = "user@gmail.com";
        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>

@jechaviz 내가 알 수없는 호스트 예외가 항상 도와주세요 얻고있다
라훌 싱

1

Gmail은 표준 프로토콜 인 POP 및 IMAP를 지원하므로 두 프로토콜의 클라이언트 측을 제공하는 모든 플랫폼, 도구, 애플리케이션, 구성 요소 또는 API가 작동합니다.

좋아하는 언어 / 플랫폼 (예 : "python"), "pop", "imap", "오픈 소스", "다운로드"또는 "리뷰"에 대한 Google 검색을 수행하는 것이 좋습니다. 당신은 옵션을 얻습니다.

수많은 무료 응용 프로그램과 구성 요소가 있으며 가치가있는 몇 가지를 선택하고 리뷰를 확인한 다음 다운로드하여 즐기십시오.


1

Gmail에 연결하려면 SSL이 필요하다는 사실을 알고 있어야합니다 (POP3 및 IMAP 모두-이것은 물론 포트 25를 제외하고 SMTP 서버에도 해당되지만 다른 이야기입니다).


1

다음은 Groovy (Java Platform 용 동적 언어)로 은행 명세서를 다운로드하기 위해 작성한 것 입니다.

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 = "gmailuser@gmail.com"
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;

}


0

Java 의 경우 G4J 가 사용됩니다. Java를 통해 Google Mail과 통신하기위한 API 세트입니다 (홈페이지의 스크린 샷은이를 중심으로 구축 된 데모 이메일 클라이언트).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.