如何用PyDrive直接上传IMAP获取的邮件附件Payload至Google Drive?
Great question—storing attachments locally before uploading is totally unnecessary here, and we can fix this by leveraging PyDrive's ability to work with in-memory binary data directly. Here's how to do it:
Step 1: Ensure You're Targeting the Right Attachment Part
First, double-check that you're correctly identifying attachment parts in your email parsing logic. Your current code is close, but you should explicitly check for attachment in the Content-Disposition header to avoid grabbing inline content or multipart subparts:
if mail.get_content_maintype() == 'multipart': for part in mail.walk(): # Skip nested multipart parts if part.get_content_maintype() == 'multipart': continue # Only process actual attachments disposition = part.get('Content-Disposition') if disposition is not None and 'attachment' in disposition.lower(): # Get the binary payload of the attachment attachment_payload = part.get_payload(decode=True) filename = part.get_filename() content_type = part.get_content_type() # Now upload this payload directly to Drive # (See Step 2 below)
Step 2: Upload the In-Memory Payload to Google Drive
PyDrive's CreateFile object has a content attribute that accepts raw binary data—this is exactly what we need to skip local storage. Here's the code snippet to replace your file-saving/upload flow:
# Create the Drive file metadata gd_file = self.gd_box.g_drive.CreateFile({ 'title': filename, 'mimeType': content_type, # Helps Drive recognize the file type 'parents': [{"id": folder['id']}] # Target folder ID }) # Assign the in-memory binary payload directly to the file's content gd_file.content = attachment_payload # Upload to Drive gd_file.Upload() # Optional: Print confirmation print(f"Successfully uploaded {filename} to Drive (ID: {gd_file['id']})")
Why This Works
- The
contentattribute of a PyDriveFileobject is designed to handle binary data directly, so we don't need to write it to a local file first. - Specifying
mimeTypeensures Google Drive correctly categorizes the file (e.g., as an image, PDF, etc.) instead of treating it as a generic binary file.
Fixing Your Original Attempt
Your initial try used GetContentFile()—that method is for downloading content from Drive to a local file, not uploading from memory. Using gd_file.content = attachment_payload is the correct approach here.
内容的提问来源于stack exchange,提问作者r1299597

