使用Python email库获取邮件附件名称失败求助
Hey, let's troubleshoot why you're getting None instead of the actual attachment filename! I’ve dealt with this exact issue before, so here’s what’s probably going wrong and how to fix it:
1. Your code misses filenames stored in Content-Type headers
Some email attachments don’t use the Content-Disposition header to store the filename—instead, they tuck it into the name parameter of the Content-Type header. Your original code skips these entirely because it checks if Content-Disposition is None and moves on.
2. Filenames might be encoded (RFC 2047)
Many emails encode filenames with non-ASCII characters using RFC 2047 standards. The raw get_filename() call will return this encoded string (or None if it can’t parse it), so you need to decode it properly.
Here’s the fixed code
Let’s update your code to handle both cases and decode encoded filenames:
import email from email.header import decode_header def decode_filename(filename): if not filename: return None # Decode RFC 2047 encoded filenames decoded_parts = decode_header(filename) decoded_name = [] for part, encoding in decoded_parts: if isinstance(part, bytes): # Use utf-8 as fallback if encoding is unknown decoded_name.append(part.decode(encoding or 'utf-8')) else: decoded_name.append(part) return ''.join(decoded_name) def get_attachment_filename(part): # First try to get filename from Content-Disposition filename = part.get_filename() if filename: return decode_filename(filename) # If that fails, check Content-Type's name parameter for param_name, param_value in part.get_params(): if param_name.lower() == 'name': return decode_filename(param_value) # No filename found return None # Process the email mail = email.message_from_string(bytes.decode(email_body)) if mail.get_content_maintype() != 'multipart': print("This email doesn't contain attachments.") else: for part in mail.walk(): if part.get_content_maintype() == 'multipart': continue # Try to get the filename regardless of Content-Disposition attachment_name = get_attachment_filename(part) if attachment_name: print(f"Found attachment: {attachment_name}")
How this works:
- The
decode_filenamefunction handles encoded filenames, converting them to readable text. get_attachment_filenamechecks bothContent-DispositionandContent-Typeheaders for the filename.- We removed the check for
Content-Disposition is Noneso we don’t skip attachments that store filenames elsewhere.
If you’re still having issues, try adding print(part.items()) inside the loop to see all the headers for each part—this will help you spot where the filename is hiding.
内容的提问来源于stack exchange,提问作者Kuldeep

