ラベル Evernote の投稿を表示しています。 すべての投稿を表示
ラベル Evernote の投稿を表示しています。 すべての投稿を表示

2014年3月24日月曜日

PythonでEvernoteへメールを送る - 添付ファイル追加

PythonでEvernoteへメールを送る」で載せたプログラムへ、ファイル添付機能を追加しました。
合わせてクラス設計を見直しました。

# -*- coding: utf-8 -*-

# ---- CONFIGURATIONS ----
EVERNOTE_MAIL_ADDRESS = 'evernote_mail_address'
FROM_ADDRESS = 'from_address'
SMTP_HOST = 'smtp_host'
SMTP_PORT = 25
# ---- CONFIGURATIONS ----

import datetime
import mimetypes
import optparse
import os.path
import smtplib
import sys

from email import encoders
from email.header import Header
from email.mime.audio import MIMEAudio
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

class EverMailClient(object):
 def __init__(self, smtp):
  assert isinstance(smtp, smtplib.SMTP)
  self._smtp = smtp
  
 def send(self, mail):
  assert isinstance(mail, EverMail)
  msg = mail.as_MIME()
  mail_from = msg['From']
  mail_to = msg['To']
  self._smtp.sendmail(mail_from, mail_to, msg.as_string())


class EverMail(object):
 def __init__(self, title, from_address, to_address, body, attached_files):
  assert isinstance(title, EverMailTitle)
  assert isinstance(body, EverMailBody)
  self._title = title
  self._from_address = from_address
  self._to_address = to_address
  self._body = body
  self._attached_files = attached_files
  
 def as_MIME(self):
  msg = MIMEMultipart()
  msg['Subject'] = Header(str(self._title), 'utf-8')
  msg['From'] = self._from_address
  msg['To'] = self._to_address
  msg.attach(self._body.as_MIME())
  for attached_file in self._attached_files:
   msg.attach(attached_file.as_MIME())
  return msg


class EverMailTitle(object):
 def __init__(self, title, notebook, tags):
  self._title = title if title else str(datetime.datetime.now())
  self._notebook = notebook if notebook else ''
  self._tags = tags if tags else []
  
 def __str__(self):
  result = self._title
  if 0 < len(self._notebook):
   result += ' @' + self._notebook
  for tag in self._tags:
   result += ' #' + tag
  return result


class EverMailBody(object):
 def __init__(self, stdin):
  assert hasattr(stdin, 'read')
  self._stdin = stdin
  
 def as_MIME(self):
  body = sys.stdin.read()
  msg = MIMEText(bytes(body))
  msg.set_charset('utf-8')
  return msg

  
class AttachedFile(object):
 def __init__(self, path):
  self._path = path
  
 def as_MIME(self):
  ctype, encoding = mimetypes.guess_type(path)
  if ctype is None or encoding is not None:
   ctype = 'application/octet-stream'
  maintype, subtype = ctype.split('/', 1)
  msg = None
  with open(self._path, 'rb') as f:
   if maintype == 'text':
    msg = MIMEText(f.read(), _subtype=subtype)
   elif maintype == 'image':
    msg = MIMEImage(f.read(), _subtype=subtype)
   elif maintype == 'audio':
    msg = MIMEAudio(f.read(), _subtype=subtype)
   else:
    msg = MIMEBase(maintype, subtype)
    msg.set_payload(f.read())
    encoders.encode_base64(msg)
  file_name = os.path.basename(self._path) 
  msg.add_header('Content-Disposition', 'attachment', filename=file_name)
  return msg


class EverMailOptionParser(optparse.OptionParser):
 def __init__(self):
  optparse.OptionParser.__init__(self)
  self.add_option('--notebook', '-n', action='store')
  self.add_option('--tag', '-t', action='append')

    
def create_smtp_client():
 smtp = smtplib.SMTP(SMTP_HOST, SMTP_PORT)
 smtp.set_debuglevel(1)
 return smtp
 
 
if __name__ == '__main__':
 option_parser = EverMailOptionParser()
 (options, args) = option_parser.parse_args()
 note_title = args[0] if args and 0 < len(args) else ''
 title = EverMailTitle(note_title,
                       options.notebook,
                       options.tag)
 body = EverMailBody(sys.stdin)
 attached_files = []
 if 2 <= len(args):
  attached_files = [AttachedFile(path) for path in args[1]]
 mail = EverMail(title,
                 FROM_ADDRESS,
                 EVERNOTE_MAIL_ADDRESS,
                 body,
                 attached_files)
 
 smtp = None
 try:
  smtp = create_smtp_client()
  client = EverMailClient(smtp)
  client.send(mail)
 finally:
  if smtp: smtp.close()

複数ファイルを添付するとうまくいかないところが問題です。
また時間のあるときに対応したいと思います。

2014年3月17日月曜日

PythonでEvernoteへメールを送る

Evernoteへメールを送ることでノートを追加できるのはご存知かと思います。
最近、古いネットブックをUSBブートのLinuxで使用しています。ネットブック上で作成したファイルをEvernoteへアップロードしたいと思うことがあるのですが、ブラウザから操作するのは厳しいと感じています。
Pythonからメールでファイルを送るようにすればいいのではないかと思い、標準入力から読み込んだ内容をEvernoteへ送るプログラムを書きました。

プログラム
# -*- coding: utf-8 -*-
# ever_mail.py

# ---- CONFIGURATIONS ----
EVERNOTE_MAIL_ADDRESS = 'evernote_mail_address'
FROM_ADDRESS = 'from_address'
SMTP_HOST = 'smtp._host'
SMTP_PORT = 25
DEBUG = True
# ---- CONFIGURATIONS ----

import datetime
import email.header
import optparse
import smtplib
import sys

from email.mime.text import MIMEText

class EverMailClient(object):
    def __init__(self, smtp):
        assert isinstance(smtp, smtplib.SMTP)
        self._smtp = smtp

    def send(self, msg):
        assert isinstance(msg, MIMEText)
        mail_from = msg['From']
        mail_to = msg['To']
        self._smtp.sendmail(mail_from, mail_to, msg.as_string())


class EverMailTitle(object):
    def __init__(self, title, notebook, tags):
        self._title = title if title else str(datetime.datetime.now)
        self._notebook = notebook if notebook else ''
        self._tags = tags if tags else []

    def __str__(self):
        result = self._title
        if 0 < len(self._notebook):
            result += ' @' + self._notebook
        for tag in self._tags:
            result += ' #' + tag
        return result


class EverMailOptionParser(optparse.OptionParser):
    def __init__(self):
        optparse.OptionParser.__init__(self)
        self.add_option('--notebook', '-n', action='store')
        self.add_option('--tag', '-t', action='append')


def create_smtp_client():
    smtp = smtplib.SMTP(SMTP_HOST, SMTP_PORT)
    if DEBUG:
        smtp.set_debuglevel(1)
    return smtp

def create_message_from_stdin(title):
    assert isinstance(title, EverMailTitle)
    body = sys.stdin.read()
    msg = MIMEText(bytes(body))
    msg['Subject'] = email.header.Header(str(title), 'utf-8')
    msg['From'] = FROM_ADDRESS
    msg['To'] = EVERNOTE_MAIL_ADDRESS
    msg.set_charset('utf-8')
    return msg


if __name__ == '__main__':
    option_parser = EverMailOptionParser()
    (options, args) = option_parser.parse_args()
    note_title = args[0] if args and 0 < len(args) else ''
    title = EverMailTitle(note_title,
                          options.notebook,
                          options.tag)
    msg = create_message_from_stdin(title)
    smtp = None
    try:
        smtp = create_smtp_client()
        client = EverMailClient(smtp)
        client.send(msg)
    finally:
        if smtp: smtp.close()


使用例
$ cat your_important_file | python ever_mail.py TITLE -nNOTEBOOK -tTAG -tTAG

工夫したところは、optparseモジュールを使ってオプションの解析を実装したところです。
暇があれば、画像の添付なども対応したいと思います。

参考
15.5. optparse — コマンドラインオプション解析器
Eメールを送信するだけでEvernoteに簡単送信!