Làm cách nào để kết nối với Gmail và xác định thư nào có tệp đính kèm? Sau đó, tôi muốn tải xuống từng tệp đính kèm, in ra Chủ đề: và Từ: cho mỗi thư khi tôi xử lý nó.
Làm cách nào để kết nối với Gmail và xác định thư nào có tệp đính kèm? Sau đó, tôi muốn tải xuống từng tệp đính kèm, in ra Chủ đề: và Từ: cho mỗi thư khi tôi xử lý nó.
Câu trả lời:
Cái này khó đấy :-)
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! Đó là một cái gì đó. ;-) Nhưng hãy thử tương tự trong Java, chỉ cho vui!
Nhân tiện, tôi đã kiểm tra điều đó trong một trình bao, vì vậy một số lỗi có thể vẫn còn.
Thưởng thức
BIÊN TẬP:
Vì tên hộp thư có thể thay đổi từ quốc gia này sang quốc gia khác, tôi khuyên bạn nên thực hiện m.list()
và chọn một mục trong đó trước m.select("the mailbox name")
để tránh lỗi này:
imaplib.error: lệnh TÌM KIẾM bất hợp pháp ở tiểu bang AUTH, chỉ được phép ở tiểu bang ĐÃ CHỌN
Tôi không phải là chuyên gia về Perl, nhưng những gì tôi biết là GMail hỗ trợ IMAP và POP3, 2 giao thức hoàn toàn tiêu chuẩn và cho phép bạn làm điều đó.
Có lẽ điều đó sẽ giúp bạn bắt đầu.
#!/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)
chưa được kiểm tra
Hãy xem qua Mail :: Webmail :: Gmail :
NHẬN ĐÍNH KÈM
Có hai cách để nhận tệp đính kèm:
1 -> Bằng cách gửi tham chiếu đến tệp đính kèm cụ thể do 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 -> Hoặc bằng cách gửi ID tệp đính kèm và ID tin nhắn
#retrieve specific attachment
my $msgid = 'F000000000';
my $attachid = '0.1';
my $attach_ref = $gmail->get_attachment( attid => $attachid, msgid => $msgid );
(Trả về một tham chiếu đến một đại lượng vô hướng giữ dữ liệu từ tệp đính kèm.)
Trong gmail, bạn có thể lọc "có: tệp đính kèm", sử dụng nó để xác định các thư bạn sẽ nhận được khi kiểm tra. Lưu ý rằng điều này dường như cung cấp cho cả thư có tệp đính kèm (hiển thị biểu tượng kẹp giấy), cũng như hình ảnh đính kèm nội tuyến (không hiển thị kẹp giấy).
Không có API Gmail, vì vậy IMAP hoặc POP là những lựa chọn thực sự duy nhất của bạn. Các JavaMail API có thể của một số hỗ trợ cũng như bài viết rất ngắn gọn này vào file đính kèm tải về từ IMAP sử dụng Perl . Một số câu hỏi trước đây trên SO cũng có thể hữu ích.
Ví dụ PHP này cũng có thể hữu ích. Rất tiếc, từ những gì tôi có thể thấy, không có thông tin đính kèm nào được chứa trong imap_header, vì vậy, cần tải phần nội dung xuống để có thể xem trường X-Attachment-Id. (ai đó hãy chứng minh tôi sai).
Nếu bất kỳ ai trong số bạn đã cập nhật lên python 3.3, tôi đã lấy tập lệnh 2.7 từ ĐÂY và cập nhật nó lên 3.3. Cũng đã khắc phục một số vấn đề với cách gmail trả lại thông tin.
# 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)
Câu hỏi khá cũ và tại thời điểm đó Gmail API chưa có sẵn. Nhưng bây giờ Google cung cấp API Gmail để truy cập IMAP. Xem API Gmail của Google tại đây . Đồng thời xem google-api-python-client trên pypi.
/*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);
}
}
Sự phụ thuộc Maven:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.1</version>
</dependency>
Vì Gmail hỗ trợ các giao thức chuẩn POP và IMAP nên bất kỳ nền tảng, công cụ, ứng dụng, thành phần hoặc API nào cung cấp phía máy khách của một trong hai giao thức sẽ hoạt động.
Tôi khuyên bạn nên thực hiện tìm kiếm trên Google cho ngôn ngữ / nền tảng yêu thích của bạn (ví dụ: "python"), cộng với "pop", cộng với "imap", có lẽ là "mã nguồn mở", có thể là "tải xuống" hoặc "đánh giá" và xem những gì bạn nhận được các tùy chọn.
Có rất nhiều ứng dụng và thành phần miễn phí, hãy chọn một vài ứng dụng có vẻ xứng đáng, kiểm tra đánh giá, sau đó tải xuống và tận hưởng.
Đây là nội dung tôi đã viết để tải xuống bảng sao kê ngân hàng của mình trong Groovy (ngôn ngữ động cho Nền tảng 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 = "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;
}
Bạn đã xem qua các tiện ích bổ sung của bên thứ 3 GMail tại wikipedia chưa?
Đặc biệt, PhpGmailDrive là một tiện ích bổ sung mã nguồn mở mà bạn có thể sử dụng nguyên bản hoặc có thể nghiên cứu để tìm cảm hứng?
Đối với Java, bạn sẽ tìm thấy G4J được sử dụng. Đó là một tập hợp các API để giao tiếp với Google Mail qua Java (ảnh chụp màn hình trên trang chủ là một ứng dụng email trình diễn được xây dựng xung quanh điều này)