diff --git a/CHANGELOG.md b/CHANGELOG.md index 62be3114..fafa8d90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,12 @@ Given the high speed of development in the first phase, changes are being report - Added `mastodon` plugin. - Added `chat.irc` plugin. +- Added `mailgun` plugin. ### Fixed - Fixed `switchbot.status` method in case of virtual devices. -- Fixed `switchbot.status` method in case of virtual devices. +- Fixed `platypush[alexa]` optional package installation. ## [0.22.4] - 2021-10-19 diff --git a/docs/source/platypush/plugins/mailgun.rst b/docs/source/platypush/plugins/mailgun.rst new file mode 100644 index 00000000..d158bac7 --- /dev/null +++ b/docs/source/platypush/plugins/mailgun.rst @@ -0,0 +1,5 @@ +``mailgun`` +=========== + +.. automodule:: platypush.plugins.mailgun + :members: diff --git a/docs/source/plugins.rst b/docs/source/plugins.rst index 6ed7832e..5a2a4d75 100644 --- a/docs/source/plugins.rst +++ b/docs/source/plugins.rst @@ -73,6 +73,7 @@ Plugins platypush/plugins/luma.oled.rst platypush/plugins/mail.imap.rst platypush/plugins/mail.smtp.rst + platypush/plugins/mailgun.rst platypush/plugins/mastodon.rst platypush/plugins/media.chromecast.rst platypush/plugins/media.gstreamer.rst diff --git a/platypush/plugins/mailgun/__init__.py b/platypush/plugins/mailgun/__init__.py new file mode 100644 index 00000000..97d9f9e9 --- /dev/null +++ b/platypush/plugins/mailgun/__init__.py @@ -0,0 +1,65 @@ +import os +from typing import Optional, Union, Sequence + +import requests +from requests.auth import HTTPBasicAuth + +from platypush.plugins import action +from platypush.plugins.mail import MailOutPlugin + + +class MailgunPlugin(MailOutPlugin): + """ + Mailgun integration. + """ + def __init__(self, api_key: str, api_base_url: str = 'https://api.mailgun.net/v3', **kwargs): + """ + :param api_key: Mailgun API secret key. + :param api_base_url: Use ``https://api.eu.mailgun.net/v3`` if you are using an EU account. + """ + super().__init__(**kwargs) + self._api_key = api_key + self._api_base_url = api_base_url + + def send_message(self, *_, **__): + pass + + @action + def send( + self, domain: str, to: Union[str, Sequence[str]], from_: Optional[str] = None, + cc: Optional[Union[str, Sequence[str]]] = None, bcc: Optional[Union[str, Sequence[str]]] = None, + subject: str = '', body: str = '', body_type: str = 'plain', attachments: Optional[Sequence[str]] = None, + **kwargs + ): + """ + Send an email through Mailgun. + + :param domain: From which registered domain the email(s) should be sent. + :param to: Receiver(s), as comma-separated strings or list. + :param from_: Sender email address (``from`` is also supported outside of Python contexts). + :param cc: Carbon-copy addresses, as comma-separated strings or list + :param bcc: Blind carbon-copy addresses, as comma-separated strings or list + :param subject: Mail subject. + :param body: Mail body. + :param body_type: Mail body type - ``text`` or ``html``. + :param attachments: List of attachment files to send. + """ + from_ = from_ or kwargs.pop('from', None) + rs = requests.post( + f'{self._api_base_url}/{domain}/messages', + auth=HTTPBasicAuth('api', self._api_key), + data={ + 'to': ', '.join([to] if isinstance(to, str) else to), + 'subject': subject, + **{'html' if body_type == 'html' else 'text': body}, + **({'from': from_} if from_ else {}), + **({'cc': ', '.join([cc] if isinstance(cc, str) else cc)} if cc else {}), + **({'bcc': ', '.join([bcc] if isinstance(bcc, str) else bcc)} if bcc else {}), + }, + files=[os.path.expanduser(attachment) for attachment in (attachments or [])] + ) + + rs.raise_for_status() + + +# vim:sw=4:ts=4:et: diff --git a/platypush/plugins/mailgun/manifest.yaml b/platypush/plugins/mailgun/manifest.yaml new file mode 100644 index 00000000..d0b7a5db --- /dev/null +++ b/platypush/plugins/mailgun/manifest.yaml @@ -0,0 +1,3 @@ +manifest: + package: platypush.plugins.mailgun + type: plugin