summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomás Touceda <chiiph@leap.se>2014-01-22 14:48:51 -0300
committerTomás Touceda <chiiph@leap.se>2014-01-22 14:48:51 -0300
commit6200de55e78354f0a11285ea1f5916a2b9e015a7 (patch)
tree25ff7fb6a50972c5df673432e9e3f05459ab15a5
parentbf9ddcc76e4d7ffa4b6d738bd0087750f1f4f13b (diff)
parentcc516f070c938d02a7616910ef4233c390494661 (diff)
Merge remote-tracking branch 'refs/remotes/ivan/feature/add-email-string-sender'
-rw-r--r--src/emails/non-ascii-plain-subject.message14
-rw-r--r--src/gmail.py145
-rwxr-xr-xsrc/send-mail-batch.py127
-rwxr-xr-xsrc/send-mail-strings.py58
-rwxr-xr-xsrc/swaks-batch.sh26
5 files changed, 247 insertions, 123 deletions
diff --git a/src/emails/non-ascii-plain-subject.message b/src/emails/non-ascii-plain-subject.message
new file mode 100644
index 0000000..25c44f4
--- /dev/null
+++ b/src/emails/non-ascii-plain-subject.message
@@ -0,0 +1,14 @@
+Content-Type: multipart/mixed; boundary="===============1817442041=="
+MIME-Version: 1.0
+Subject: Héllò thërê - stored message - ÿȩāḩ
+From: {FROM}
+To: {TO}
+
+--===============1817442041==
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
+
+Howdy from python!
+The subject: Héllò thërê - stored message - ÿȩāḩ
+--===============1817442041==--
diff --git a/src/gmail.py b/src/gmail.py
new file mode 100644
index 0000000..4e7af04
--- /dev/null
+++ b/src/gmail.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+import mimetypes
+import os
+import smtplib
+
+from email import encoders
+from email.mime.base import MIMEBase
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
+
+
+class GMail(object):
+ """Email sender using the gmail service."""
+ SMTPSERVER = 'smtp.gmail.com:587'
+
+ def __init__(self, account, password):
+ """
+ Initializes the class.
+ You should provide credentials in order to login into gmail.
+
+ :param account: the username@gmail.com account to use for sending.
+ :type account: str
+ :param password: the password for the account.
+ :type password: str
+ """
+ self._from = account
+ login = account.split('@')[0]
+ self._server = smtplib.SMTP(self.SMTPSERVER)
+ self._server.starttls()
+ self._server.login(login, password)
+
+ def __del__(self):
+ """
+ Quits the server.
+ """
+ self._server.quit()
+
+ def _get_attachment(self, file_path):
+ """
+ Creates the MIMEBase attachment for the file 'file_path'.
+
+ Might raise:
+ IOError
+
+ :param file_path: the file from to generate the attachment from.
+ :type file_path: str
+
+ :return: the MIMEBase attachment.
+ :rtype: MIMEBase
+ """
+ ctype, encoding = mimetypes.guess_type(file_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)
+
+ # Read the file, this may rise IOError
+ with open(file_path, 'rb') as fp:
+ the_file = MIMEBase(maintype, subtype)
+ the_file.set_payload(fp.read())
+
+ # Encode the payload using Base64
+ encoders.encode_base64(the_file)
+
+ # Set the filename parameter
+ the_file.add_header('Content-Disposition', 'attachment',
+ filename=os.path.basename(file_path))
+
+ return the_file
+
+ def send_email(self, to_addr_list, cc_addr_list, subject,
+ message, attachments=None):
+ """
+ Sends an email.
+
+ :param to_addr_list: a list of addresses to send the email.
+ :type to_addr_list: list of str
+ :param cc_addr_list: a list of addresses to send (as CC) the email.
+ :type cc_addr_list: list of str
+ :param subject: the subject of the email
+ :type subject: str
+ :param message: the message to send
+ :type message: str
+ :param attachments: a list of paths for the files to attach.
+ :type attachments: list of str
+
+ :return: an empty dict if everything went ok or
+ the problems result of sending the email(s).
+ :rtype: dict
+ """
+ # Create the container (outer) email message.
+ msg = MIMEMultipart()
+ msg['Subject'] = subject
+ msg['From'] = self._from
+ msg['To'] = ', '.join(to_addr_list)
+
+ if cc_addr_list:
+ msg['Cc'] = ', '.join(cc_addr_list)
+
+ # Add the message's text
+ msg.attach(MIMEText(message))
+
+ problems = ''
+ if attachments is not None:
+ # Attach every file in the attachment parameter
+ for file_path in attachments:
+ try:
+ the_file = self._get_attachment(file_path)
+ msg.attach(the_file)
+ except IOError:
+ problems += "Could not attach {0!r}\n".format(file_path)
+
+ message = msg.as_string()
+ try:
+ result = self._server.sendmail(self._from, to_addr_list, message)
+ except Exception as e:
+ result = {'Exception': repr(e)}
+
+ if problems:
+ result['Attachments'] = problems
+
+ return result
+
+ def send_email_string(self, mail, to):
+ """
+ Sends an email from an already created email as a string.
+
+ :param mail: the mail to send
+ :type mail: str
+ :param to: a address to send the email.
+ :type to: str
+
+ :return: an empty dict if everything went ok or
+ the problems result of sending the email(s).
+ :rtype: dict
+ """
+ try:
+ result = self._server.sendmail(self._from, [to], mail)
+ except Exception as e:
+ result = {'Exception': repr(e)}
+
+ return result
diff --git a/src/send-mail-batch.py b/src/send-mail-batch.py
index fceea74..4d889f7 100755
--- a/src/send-mail-batch.py
+++ b/src/send-mail-batch.py
@@ -1,133 +1,14 @@
#!/usr/bin/env python
# encoding: utf-8
# import getpass
-import mimetypes
import os
import sys
import random
-import smtplib
import time
from ConfigParser import SafeConfigParser
-from email import encoders
-from email.mime.base import MIMEBase
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-
-
-class GMail(object):
- """Email sender using the gmail service."""
- SMTPSERVER = 'smtp.gmail.com:587'
-
- def __init__(self, account, password):
- """
- Initializes the class.
- You should provide credentials in order to login into gmail.
-
- :param account: the username@gmail.com account to use for sending.
- :type account: str
- :param password: the password for the account.
- :type password: str
- """
- self._from = account
- login = account.split('@')[0]
- self._server = smtplib.SMTP(self.SMTPSERVER)
- self._server.starttls()
- self._server.login(login, password)
-
- def __del__(self):
- """
- Quits the server.
- """
- self._server.quit()
-
- def _get_attachment(self, file_path):
- """
- Creates the MIMEBase attachment for the file 'file_path'.
-
- Might raise:
- IOError
-
- :param file_path: the file from to generate the attachment from.
- :type file_path: str
-
- :return: the MIMEBase attachment.
- :rtype: MIMEBase
- """
- ctype, encoding = mimetypes.guess_type(file_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)
-
- # Read the file, this may rise IOError
- with open(file_path, 'rb') as fp:
- the_file = MIMEBase(maintype, subtype)
- the_file.set_payload(fp.read())
-
- # Encode the payload using Base64
- encoders.encode_base64(the_file)
-
- # Set the filename parameter
- the_file.add_header('Content-Disposition', 'attachment',
- filename=os.path.basename(file_path))
-
- return the_file
-
- def send_email(self, to_addr_list, cc_addr_list, subject,
- message, attachments=None):
- """
- Sends an email.
-
- :param to_addr_list: a list of addresses to send the email.
- :type to_addr_list: list of str
- :param cc_addr_list: a list of addresses to send (as CC) the email.
- :type cc_addr_list: list of str
- :param subject: the subject of the email
- :type subject: str
- :param message: the message to send
- :type message: str
- :param attachments: a list of paths for the files to attach.
- :type attachments: list of str
-
- :return: an empty dict if everything went ok or
- the problems result of sending the email(s).
- :rtype: dict
- """
- # Create the container (outer) email message.
- msg = MIMEMultipart()
- msg['Subject'] = subject
- msg['From'] = self._from
- msg['To'] = ', '.join(to_addr_list)
-
- if cc_addr_list:
- msg['Cc'] = ', '.join(cc_addr_list)
-
- # Add the message's text
- msg.attach(MIMEText(message))
-
- problems = ''
- if attachments is not None:
- # Attach every file in the attachment parameter
- for file_path in attachments:
- try:
- the_file = self._get_attachment(file_path)
- msg.attach(the_file)
- except IOError:
- problems += "Could not attach {0!r}\n".format(file_path)
-
- message = msg.as_string()
- try:
- result = self._server.sendmail(self._from, to_addr_list, message)
- except Exception as e:
- result['Exception'] = repr(e)
-
- if problems:
- result['Attachments'] = problems
-
- return result
+from gmail import GMail
def send_test_mail(subject):
@@ -191,10 +72,10 @@ gmail = GMail(FROM, SECRET)
print "Sending {0} mails batch...".format(MAX_MAILS)
-count = 1
-while count <= MAX_MAILS:
+count = 0
+while count < MAX_MAILS:
idx = (count % len(lorem_subjects))
- subject = "[TEST] {0:03} - {1}".format(count, lorem_subjects[idx])
+ subject = "[TEST] {0:03} - {1}".format(count+1, lorem_subjects[idx])
print "Sending '{0}' ... ".format(subject),
try:
problems = send_test_mail(subject)
diff --git a/src/send-mail-strings.py b/src/send-mail-strings.py
new file mode 100755
index 0000000..b682c90
--- /dev/null
+++ b/src/send-mail-strings.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# encoding: utf-8
+# import getpass
+import os
+import sys
+
+from ConfigParser import SafeConfigParser
+
+from gmail import GMail
+
+
+# Read credentials from options file
+parser = SafeConfigParser()
+parser.read('options.cfg')
+try:
+ FROM = parser.get('Credentials', 'account')
+ SECRET = parser.get('Credentials', 'password')
+ TO = [parser.get('Configs', 'to')]
+ MAX_MAILS = parser.getint('Configs', 'mails_amount')
+except Exception as e:
+ print "Problem reading options.cfg"
+ print "Exception: {0!r}".format(e)
+ sys.exit()
+
+
+# create the GMail global object
+gmail = GMail(FROM, SECRET)
+
+directory = './emails/'
+file_list = []
+
+for filename in os.listdir(directory):
+ path = os.path.join(directory, filename)
+ if os.path.isfile(path):
+ file_list.append(path)
+
+print "Sending {0} mail(s)...".format(len(file_list))
+
+for mail_file in file_list:
+ print "Sending '{0}' ... ".format(mail_file),
+ with open(mail_file) as f:
+ email = f.read()
+
+ try:
+ # replace placeholders with actual data
+ email = email.format(FROM=FROM, TO=','.join(TO))
+ except KeyError:
+ print "Warning: missing placeholder in {0}".format(mail_file)
+
+ try:
+ problems = gmail.send_email_string(email, TO)
+ except Exception as e:
+ problems = repr(e)
+
+ if problems:
+ print "Problems: {0!r}".format(problems)
+ else:
+ print 'ok.'
diff --git a/src/swaks-batch.sh b/src/swaks-batch.sh
new file mode 100755
index 0000000..1e81210
--- /dev/null
+++ b/src/swaks-batch.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+# This scripts depends on swaks: http://www.jetmore.org/john/code/swaks/
+
+if [ -n "$1" ]; then
+ SWAKS=$1
+else
+ SWAKS=swaks
+fi
+
+# if [[ "$SWAKS" == "" ]]; then
+if ! `hash $SWAKS 2>/dev/null`; then
+ echo "Error: I need swaks to work."
+ echo "You can get swaks from: http://www.jetmore.org/john/code/swaks/"
+ echo "If you already have it, you can send its location as a first parameter of the script."
+ echo "E.g.: $0 /path/to/swaks"
+ exit 1
+fi
+
+# Customize this in order to test the desired accounts
+FROM=ivan@dev.bitmask.net
+TO=test_123@dev.bitmask.net
+
+# NOTE: Add the swak commands below here:
+
+# Unicode subject and body, without charset specification
+$SWAKS --to $TO --from $FROM --header "Subject: Test -- áèīôü" --body "Howdy from swaks. ýëąĥ" --helo 'asdf.com'