Java 如何从 Gmail 下载所有带有附件的电子邮件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/348630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:41:59  来源:igfitidea点击:

How can I download all emails with attachments from Gmail?

javapythonperlgmail

提问by

How do I connect to Gmail and determine which messages have attachments? I then want to download each attachment, printing out the Subject: and From: for each message as I process it.

如何连接到 Gmail 并确定哪些邮件带有附件?然后我想下载每个附件,在我处理每条消息时打印出主题:和发件人:。

采纳答案by e-satis

Hard one :-)

难一:-)

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! That was something. ;-) But try the same in Java, just for fun!

哇!那是一些东西。;-) 但是在 Java 中尝试相同的方法,只是为了好玩!

By the way, I tested that in a shell, so some errors likely remain.

顺便说一下,我在 shell 中测试了它,所以可能会保留一些错误。

Enjoy

享受

EDIT:

编辑:

Because mail-box names can change from one country to another, I recommend doing m.list()and picking an item in it before m.select("the mailbox name")to avoid this error:

由于邮箱名称可能会从一个国家/地区更改为另一个国家/地区,因此我建议您先在其中执行m.list()并选择一个项目,m.select("the mailbox name")以避免出现此错误:

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

imaplib.error:命令 SEARCH 在状态 AUTH 中非法,仅在状态 SELECTED 中允许

回答by Jeroen Landheer

I'm not an expert on Perl, but what I do know is that GMail supports IMAP and POP3, 2 protocols that are completely standard and allow you to do just that.

我不是 Perl 方面的专家,但我所知道的是 GMail 支持 IMAP 和 POP3,这 2 种协议是完全标准的并且允许您这样做。

Maybe that helps you to get started.

也许这可以帮助您入门。

回答by Kevin Haines

Within gmail, you can filter on "has:attachment", use it to identify the messages you should be getting when testing. Note this appears to give both messages with attached files (paperclip icon shown), as well as inline attached images (no paperclip shown).

在 gmail 中,您可以过滤“has:attachment”,使用它来确定您在测试时应该收到的邮件。请注意,这似乎提供了带有附加文件(显示回形针图标)的消息,以及内嵌附加图像(未显示回形针)。

There is no Gmail API, so IMAP or POP are your only real options. The JavaMail APImay be of some assistance as well as this very terse article on downloading attachments from IMAP using Perl. Some previous questionshere on SO may also help.

没有 Gmail API,因此 IMAP 或 POP 是您唯一真正的选择。该的JavaMail API可能会有一些帮助,以及对这个非常简洁的文章下载附件从IMAP使用Perl以前关于 SO 的一些问题也可能有所帮助。

This PHP examplemay help too. Unfortunately from what I can see, there is no attachment information contained within the imap_header, so downloading the body is required to be able to see the X-Attachment-Id field. (someone please prove me wrong).

这个PHP 示例也可能有所帮助。不幸的是,据我所知,imap_header 中没有包含附件信息,因此需要下载正文才能看到 X-Attachment-Id 字段。(有人请证明我错了)。

回答by Rob Williams

Since Gmail supports the standard protocols POP and IMAP, any platform, tool, application, component, or API that provides the client side of either protocol should work.

由于 Gmail 支持标准协议 POP 和 IMAP,因此提供任一协议客户端的任何平台、工具、应用程序、组件或 API 都可以正常工作。

I suggest doing a Google search for your favorite language/platform (e.g., "python"), plus "pop", plus "imap", plus perhaps "open source", plus perhaps "download" or "review", and see what you get for options.

我建议用谷歌搜索你最喜欢的语言/平台(例如,“python”),加上“pop”,加上“imap”,加上“开源”,加上“下载”或“评论”,看看有什么你得到了选择。

There are numerous free applications and components, pick a few that seem worthy, check for reviews, then download and enjoy.

有许多免费的应用程序和组件,选择一些看起来值得的,检查评论,然后下载并享受。

回答by moster67

You should be aware of the fact that you need SSL to connect to GMail (both for POP3 and IMAP - this is of course true also for their SMTP-servers apart from port 25 but that's another story).

您应该意识到您需要 SSL 才能连接到 GMail(对于 POP3 和 IMAP - 除了端口 25 之外的 SMTP 服务器当然也是如此,但那是另一回事)。

回答by toolkit

Have you taken a look at the GMail 3rd party add-onsat wikipedia?

您是否查看过维基百科的GMail 3rd 方附加组件

In particular, PhpGmailDriveis an open source add-on that you may be able to use as-is, or perhaps study for inspiration?

特别是,PhpGmailDrive是一个开源插件,您可以按原样使用,或者可以学习以获取灵感?

回答by jfs

#!/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)

untested

未经测试

  1. Make sure TOS allows such scripts otherwise you account will be suspended
  2. There might be better options: GMail offline mode, Thunderbird + ExtractExtensions, GmailFS, Gmail Drive, etc.
  1. 确保 TOS 允许此类脚本,否则您的帐户将被暂停
  2. 可能有更好的选择:GMail 离线模式、Thunderbird + ExtractExtensions、GmailFS、Gmail Drive 等。

回答by Brian Agnew

For Java, you will find G4Jof use. It's a set of APIs to communicate with Google Mail via Java (the screenshot on the homepage is a demonstration email client built around this)

对于 Java,您会发现使用G4J。它是一组通过 Java 与 Google Mail 通信的 API(主页上的截图是围绕此构建的演示电子邮件客户端)

回答by JDrago

Take a look at Mail::Webmail::Gmail:

看看Mail::Webmail::Gmail

GETTING ATTACHMENTS

获取附件

There are two ways to get an attachment:

获取附件有两种方式:

1 -> By sending a reference to a specific attachment returned by get_indv_email

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 -> Or by sending the attachment ID and message ID

2 -> 或者通过发送附件 ID 和消息 ID

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

( Returns a reference to a scalar that holds the data from the attachment. )

(返回对保存附件数据的标量的引用。)

回答by msanjay

Here's something I wrote to download my bank statements in Groovy(dynamic language for the Java Platform).

这是我在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;

}