| #!/usr/bin/env python3 | |
| """Send the contents of a directory as a MIME message.""" | |
| import os | |
| import smtplib | |
| # For guessing MIME type based on file name extension | |
| import mimetypes | |
| from argparse import ArgumentParser | |
| from email.message import EmailMessage | |
| from email.policy import SMTP | |
| def main(): | |
| parser = ArgumentParser(description="""\ | |
| Send the contents of a directory as a MIME message. | |
| Unless the -o option is given, the email is sent by forwarding to your local | |
| SMTP server, which then does the normal delivery process. Your local machine | |
| must be running an SMTP server. | |
| """) | |
| parser.add_argument('-d', '--directory', | |
| help="""Mail the contents of the specified directory, | |
| otherwise use the current directory. Only the regular | |
| files in the directory are sent, and we don't recurse to | |
| subdirectories.""") | |
| parser.add_argument('-o', '--output', | |
| metavar='FILE', | |
| help="""Print the composed message to FILE instead of | |
| sending the message to the SMTP server.""") | |
| parser.add_argument('-s', '--sender', required=True, | |
| help='The value of the From: header (required)') | |
| parser.add_argument('-r', '--recipient', required=True, | |
| action='append', metavar='RECIPIENT', | |
| default=[], dest='recipients', | |
| help='A To: header value (at least one required)') | |
| args = parser.parse_args() | |
| directory = args.directory | |
| if not directory: | |
| directory = '.' | |
| # Create the message | |
| msg = EmailMessage() | |
| msg['Subject'] = f'Contents of directory {os.path.abspath(directory)}' | |
| msg['To'] = ', '.join(args.recipients) | |
| msg['From'] = args.sender | |
| msg.preamble = 'You will not see this in a MIME-aware mail reader.\n' | |
| for filename in os.listdir(directory): | |
| path = os.path.join(directory, filename) | |
| if not os.path.isfile(path): | |
| continue | |
| # Guess the content type based on the file's extension. Encoding | |
| # will be ignored, although we should check for simple things like | |
| # gzip'd or compressed files. | |
| ctype, encoding = mimetypes.guess_file_type(path) | |
| if ctype is None or encoding is not None: | |
| # No guess could be made, or the file is encoded (compressed), so | |
| # use a generic bag-of-bits type. | |
| ctype = 'application/octet-stream' | |
| maintype, subtype = ctype.split('/', 1) | |
| with open(path, 'rb') as fp: | |
| msg.add_attachment(fp.read(), | |
| maintype=maintype, | |
| subtype=subtype, | |
| filename=filename) | |
| # Now send or store the message | |
| if args.output: | |
| with open(args.output, 'wb') as fp: | |
| fp.write(msg.as_bytes(policy=SMTP)) | |
| else: | |
| with smtplib.SMTP('localhost') as s: | |
| s.send_message(msg) | |
| if __name__ == '__main__': | |
| main() |