From b79b548bcbb8e071d8bc5009115c4b573eb8c4bd Mon Sep 17 00:00:00 2001 From: Idan Regev Date: Thu, 22 Dec 2022 11:42:47 +0200 Subject: [PATCH 1/6] Fix nbconvert as advised in issue #1 --- README.md | 5 +++++ nb2mail/__init__.py | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index be1f531..0ece850 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ To generate a mail and send it later with another process (eg `sendmail`): jupyter nbconvert --execute --to mail notebook.ipynb +### SMTP Example To convert and send a mail via gmail, you can set the environment variables and declare a postprocessor with `--post`: @@ -43,6 +44,10 @@ and then run: jupyter nbconvert --config config.py demo.ipynb +### 3rd party email distributor Example +Insread of using SMTP to send emails, one can use 3rd party provider. +This is an example for using [mailgun](examples/mailgun.ipynb) as a 3rd party provider + ## Configuring Mail Headers In the notebook metadata, you can set mail headers by adding a `nb2mail` block: diff --git a/nb2mail/__init__.py b/nb2mail/__init__.py index ccc805a..106ef9c 100644 --- a/nb2mail/__init__.py +++ b/nb2mail/__init__.py @@ -62,6 +62,7 @@ def __init__(self, config=None, **kw): config : config User configuration instance. """ + self.template_file=os.path.join(os.path.dirname(__file__), "templates", "mail.tpl") super(MailExporter, self).__init__(config=config, **kw) self.register_filter('basename_attach', basename_attach) self.register_filter('data_attach', data_attach) @@ -72,9 +73,10 @@ def _file_extension_default(self): @default('template_file') def _template_file_default(self): - return 'mail.tpl' + # return os.path.join(os.path.dirname(__file__), "templates", "mail.tpl") + "mail.tpl" - output_mimetype = 'multipart/mixed' + output_mimetype = '' @default('raw_mimetypes') def _raw_mimetypes_default(self): From aaa07923a46536691052b8402bfed87c715e185a Mon Sep 17 00:00:00 2001 From: Idan Regev Date: Thu, 22 Dec 2022 11:43:28 +0200 Subject: [PATCH 2/6] Add examples for 3rd party mail provider (not SMTP) --- examples/mailgun.ipynb | 172 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 examples/mailgun.ipynb diff --git a/examples/mailgun.ipynb b/examples/mailgun.ipynb new file mode 100644 index 0000000..82f1a17 --- /dev/null +++ b/examples/mailgun.ipynb @@ -0,0 +1,172 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Working example\n", + "Convert jupyter notebook to email message and mail it with mailgun" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Convert jupyter to .mail file\n", + "1. `jupyter nbconvert --to mail test.ipynb`\n", + "2. run this notebook" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Mailgun credentials\n", + "```python\n", + "{\n", + " \"From\":\"from mail example\",\n", + " \"To\" : \"to mail example\",\n", + " \"MAILGUN_URL\" : \"mailgun sending url\",\n", + " \"MAILGUN_KEY\" : \"key secret\"\n", + "}\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add addresses to mime message " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from email import message_from_file\n", + "from email.mime.message import MIMEMessage\n", + "import json\n", + "def mail_prep(subject, filename, cred='cred_mail.json'):\n", + "\t'''\n", + "\tAdd subject\n", + "\tsubject : subject of the mail thread\n", + "\tfilename : .mail filename (already exists mime filename)\n", + "\tcred (dict): mailgun credentials file\n", + "\t'''\n", + "\tcred_dict = json.load(open(cred))\n", + "\n", + "\tmsg = MIMEMessage(message_from_file(open(filename)))\n", + "\tmsg['Subject'] = subject\n", + "\tmsg['From'] = cred_dict['From']\n", + "\tmsg['To'] = cred_dict['To']\n", + "\t\n", + "\t# filename='outgoing.msg'\n", + "\t# with open(filename, 'wb') as f:\n", + "\t# \tf.write(bytes(msg))\n", + "\treturn msg" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "subject='testing 12345678'\n", + "modified_msg=mail_prep(subject, 'mail/test.mail')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Send mailgun raw mime message" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import json\n", + "\n", + "def mailgun_send(msg, cred='cred_mail.json'):\n", + "\t'''\n", + "\tfilename : abc.msg email filename\n", + "\tcred (dict): mailgun credentials file\n", + "\t'''\n", + "\tcred_dict = json.load(open(cred))\n", + "\n", + "\treturn requests.post(\n", + "\t\tf\"{cred_dict['MAILGUN_URL']}.mime\",\n", + "\t\tauth=(\"api\", cred_dict['MAILGUN_KEY']),\n", + "\t\tdata={\"to\": cred_dict['To']},\n", + "\t\tfiles={\"message\": bytes(msg)}\n", + "\t)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mailgun_send(modified_msg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py3env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "0f130d28ea552d45a6da6317af870e1a4a314464082fb72b4db9d63620c1bd57" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b220c431b131672aeda1d4940d4df95a99577be9 Mon Sep 17 00:00:00 2001 From: Idan Regev Date: Mon, 2 Jan 2023 08:33:43 +0200 Subject: [PATCH 3/6] Python 3 only add a constraint to only support python 3. since backward compatibility is broken for python2 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 8815312..773b5b0 100644 --- a/setup.py +++ b/setup.py @@ -8,6 +8,7 @@ author='Neal Fultz', author_email='nfultz@gmail.com', license='BSD', + python_requires='>=3.8, <4', packages=['nb2mail'], install_requires=['jupyter'], zip_safe=False, From 92234131283bd9c254ce6c4cfd9663b971c043cf Mon Sep 17 00:00:00 2001 From: Idan Regev Date: Tue, 3 Jan 2023 09:31:04 +0200 Subject: [PATCH 4/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ece850..5e21155 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ and then run: jupyter nbconvert --config config.py demo.ipynb ### 3rd party email distributor Example -Insread of using SMTP to send emails, one can use 3rd party provider. +Instead of using SMTP to send emails, one can use 3rd party provider. This is an example for using [mailgun](examples/mailgun.ipynb) as a 3rd party provider ## Configuring Mail Headers From 239763c1b14c217ff6e09b91cb83962e5e9836e9 Mon Sep 17 00:00:00 2001 From: Idan Regev Date: Tue, 3 Jan 2023 09:48:40 +0200 Subject: [PATCH 5/6] Update __init__.py --- nb2mail/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nb2mail/__init__.py b/nb2mail/__init__.py index 106ef9c..3bcf029 100644 --- a/nb2mail/__init__.py +++ b/nb2mail/__init__.py @@ -74,7 +74,7 @@ def _file_extension_default(self): @default('template_file') def _template_file_default(self): # return os.path.join(os.path.dirname(__file__), "templates", "mail.tpl") - "mail.tpl" + return "mail.tpl" output_mimetype = '' From c84e98728cc556d329989d5cec904b4c715e68c1 Mon Sep 17 00:00:00 2001 From: Idan Regev Date: Tue, 3 Jan 2023 13:14:19 +0200 Subject: [PATCH 6/6] multi ver support --- nb2mail/__init__.py | 11 ++++++++--- setup.py | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/nb2mail/__init__.py b/nb2mail/__init__.py index 3bcf029..61a8807 100644 --- a/nb2mail/__init__.py +++ b/nb2mail/__init__.py @@ -62,7 +62,9 @@ def __init__(self, config=None, **kw): config : config User configuration instance. """ - self.template_file=os.path.join(os.path.dirname(__file__), "templates", "mail.tpl") + if sys.version_info[0] == 3: + # https://stackoverflow.com/questions/27376907/how-to-detect-python-version-2-or-3-in-script + self.template_file=os.path.join(os.path.dirname(__file__), "templates", "mail.tpl") super(MailExporter, self).__init__(config=config, **kw) self.register_filter('basename_attach', basename_attach) self.register_filter('data_attach', data_attach) @@ -73,10 +75,13 @@ def _file_extension_default(self): @default('template_file') def _template_file_default(self): - # return os.path.join(os.path.dirname(__file__), "templates", "mail.tpl") return "mail.tpl" - output_mimetype = '' + if sys.version_info[0] == 2: + # https://stackoverflow.com/questions/27376907/how-to-detect-python-version-2-or-3-in-script + output_mimetype = 'multipart/mixed' + else: + output_mimetype = '' @default('raw_mimetypes') def _raw_mimetypes_default(self): diff --git a/setup.py b/setup.py index 773b5b0..8815312 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,6 @@ author='Neal Fultz', author_email='nfultz@gmail.com', license='BSD', - python_requires='>=3.8, <4', packages=['nb2mail'], install_requires=['jupyter'], zip_safe=False,