mail#

Description#

Plugin to:

  • Monitor one or more mailboxes, and emit events when new messages are received, seen, flagged or unflagged.

  • Send mail messages.

  • Search for messages in a mailbox.

Example accounts configuration:

mail:
    # Display name to be used for outgoing emails. Default:
    # the `from` parameter will be used from `MailPlugin.send <https://docs.platypush.tech/platypush/plugins/mail.html#platypush.plugins.mail.MailPlugin.send>`_,
    # and, if missing, the username from the account configuration
    # will be used.
    display_name: My Name

    # How often we should poll for updates (default: 60 seconds)
    poll_interval: 60

    # Connection timeout (default: 20 seconds)
    # Can be overridden on a per-account basis
    timeout: 20

    # Domain to be used for outgoing emails. Default: inferred
    # from the account configuration
    domain: example.com

    accounts:
        - name: "My Local Account"
          username: me@mydomain.com
          password: my-password

          # The default flag sets this account as the default one
          # for mail retrieval and sending if no account is
          # specified on an action. If multiple accounts are set
          # and none is set as default, and no account is specified
          # on an action, then the first configured account will be
          # used.
          default: true

          # Alternatively, you can run an external command
          # to get the password
          # password_cmd: "pass show mail/example.com"

          # Path to a custom certfile if the mail server uses a
          # self-signed certificate
          # certfile: /path/to/certfile

          # Path to a custom keyfile if the mail server requires
          # client authentication. It requires certfile to be set
          # too
          # keyfile: /path/to/keyfile

          incoming:
              # Supported protocols: imap, imaps
              server: imaps://mail.example.com:993

          outgoing:
              # The `incoming` and `outgoing` configurations can
              # override the global `username` and `password` and
              # other authentication parameters of the account
              username: me
              password: my-smtp-password

              # Supported protocols: smtp, smtps, smtp+starttls,
              server: smtps://mail.example.com:465

          # These folders will be monitored for new messages
          monitor_folders:
              - All Mail

        - name: "GMail"
          username: me@gmail.com

          # Access token, if the mail server supports OAuth2
          # access_token: my-access-token

          # OAuth mechanism, if the mail server supports OAuth2
          # (default: XOAUTH2)
          # oauth_mechanism: XOAUTH2

          # OAuth vendor, if the mail server supports OAuth2
          # oauth_vendor: GOOGLE

          incoming:
              # Defaults to port 993 for IMAPS if no port is
              # specified on the URL
              server: imaps://imap.gmail.com

          outgoing:
              # Defaults to port 465 for SMTPS if no port is
              # specified on the URL
              server: smtps://smtp.gmail.com

          monitor_folders:
              - INBOX
              - Sent

Configuration#

mail:
  # [Required]
  # List of available mailboxes/accounts.
  accounts:   # type=List[Dict[str, Any]]

  # [Optional]
  # Timeout for the mail server connection (default: 20
  # seconds).
  # timeout: 20.0  # type=float

  # [Optional]
  # How often the plugin should poll for new messages
  # (default: 60 seconds).
  # poll_interval: 60.0  # type=float

  # [Optional]
  # How long we should wait for any running
  # threads/processes to stop before exiting (default: 5 seconds).
  # stop_timeout: 5  # type=Optional[float]

  # [Optional]
  # If set to True then the plugin will not monitor
  # for new events. This is useful if you want to run a plugin in
  # stateless mode and only leverage its actions, without triggering any
  # events. Defaults to False.
  # disable_monitor: False  # type=bool

Dependencies#

pip

pip install dnspython imapclient

Alpine

apk add py3-dnspython

Debian

apt install python3-dnspython

Fedora

yum install python-dnspython

Arch Linux

pacman -S python-dnspython

Triggered events#

Actions#

Module reference#

class platypush.plugins.mail.MailPlugin(accounts: List[Dict[str, Any]], timeout: float = 20.0, poll_interval: float = 60.0, **kwargs)[source]#

Bases: RunnablePlugin

Plugin to:

  • Monitor one or more mailboxes, and emit events when new messages are received, seen, flagged or unflagged.

  • Send mail messages.

  • Search for messages in a mailbox.

__init__(accounts: List[Dict[str, Any]], timeout: float = 20.0, poll_interval: float = 60.0, **kwargs)[source]#

Example accounts configuration:

mail:
    # Display name to be used for outgoing emails. Default:
    # the `from` parameter will be used from :meth:`.send`,
    # and, if missing, the username from the account configuration
    # will be used.
    display_name: My Name

    # How often we should poll for updates (default: 60 seconds)
    poll_interval: 60

    # Connection timeout (default: 20 seconds)
    # Can be overridden on a per-account basis
    timeout: 20

    # Domain to be used for outgoing emails. Default: inferred
    # from the account configuration
    domain: example.com

    accounts:
        - name: "My Local Account"
          username: me@mydomain.com
          password: my-password

          # The default flag sets this account as the default one
          # for mail retrieval and sending if no account is
          # specified on an action. If multiple accounts are set
          # and none is set as default, and no account is specified
          # on an action, then the first configured account will be
          # used.
          default: true

          # Alternatively, you can run an external command
          # to get the password
          # password_cmd: "pass show mail/example.com"

          # Path to a custom certfile if the mail server uses a
          # self-signed certificate
          # certfile: /path/to/certfile

          # Path to a custom keyfile if the mail server requires
          # client authentication. It requires certfile to be set
          # too
          # keyfile: /path/to/keyfile

          incoming:
              # Supported protocols: imap, imaps
              server: imaps://mail.example.com:993

          outgoing:
              # The `incoming` and `outgoing` configurations can
              # override the global `username` and `password` and
              # other authentication parameters of the account
              username: me
              password: my-smtp-password

              # Supported protocols: smtp, smtps, smtp+starttls,
              server: smtps://mail.example.com:465

          # These folders will be monitored for new messages
          monitor_folders:
              - All Mail

        - name: "GMail"
          username: me@gmail.com

          # Access token, if the mail server supports OAuth2
          # access_token: my-access-token

          # OAuth mechanism, if the mail server supports OAuth2
          # (default: XOAUTH2)
          # oauth_mechanism: XOAUTH2

          # OAuth vendor, if the mail server supports OAuth2
          # oauth_vendor: GOOGLE

          incoming:
              # Defaults to port 993 for IMAPS if no port is
              # specified on the URL
              server: imaps://imap.gmail.com

          outgoing:
              # Defaults to port 465 for SMTPS if no port is
              # specified on the URL
              server: smtps://smtp.gmail.com

          monitor_folders:
              - INBOX
              - Sent
Parameters:
  • accounts – List of available mailboxes/accounts.

  • poll_interval – How often the plugin should poll for new messages (default: 60 seconds).

  • timeout – Timeout for the mail server connection (default: 20 seconds).

add_flags(messages: List[int], flags: str | List[str], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Add a set of flags to the specified set of message IDs.

Parameters:
  • messages – List of message IDs.

  • flags

    List of flags to be added. Examples:

    ['Flagged']
    ['Seen', 'Deleted']
    ['Junk']
    

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

copy_messages(messages: List[int], destination: str, source: str = 'INBOX', account: str | int | Account | None = None)[source]#

Copy a set of messages IDs from a folder to another.

Parameters:
  • messages – List of message IDs.

  • source – Source folder.

  • destination – Destination folder.

  • account – Account name or index (default: default account).

create_folder(folder: str, account: str | int | Account | None = None)[source]#

Create a folder on the server.

Parameters:
  • folder – Folder name.

  • account – Account name or index (default: default account).

delete_folder(folder: str, account: str | int | Account | None = None)[source]#

Delete a folder from the server.

Parameters:
  • folder – Folder name.

  • account – Account name or index (default: default account).

delete_messages(messages: List[int], folder: str = 'INBOX', expunge: bool = True, account: str | int | Account | None = None)[source]#

Set a specified set of message IDs as deleted.

Parameters:
  • messages – List of message IDs.

  • folder – IMAP folder (default: INBOX).

  • expunge – If set then the messages will also be expunged from the folder, otherwise they will only be marked as deleted (default: True).

  • account – Account name or index (default: default account).

expunge_messages(messages: List[int], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

When messages is not set, remove all the messages from folder marked as Deleted.

Parameters:
  • folder – IMAP folder (default: INBOX).

  • messages – List of message IDs to expunge (default: all those marked as Deleted).

  • account – Account name or index (default: default account).

flag_message(message: int, folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Add a flag/star to the specified set of message ID.

Parameters:
  • message – Message ID.

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

flag_messages(messages: List[int], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Add a flag/star to the specified set of message IDs.

Parameters:
  • messages – List of message IDs.

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

get_folders(folder: str = '', pattern: str = '*', account: str | int | Account | None = None) List[Dict[str, str]][source]#

Get the list of all the folders hosted on the server or those matching a pattern.

Parameters:
  • folder – Base folder (default: root).

  • pattern – Pattern to search (default: None).

  • account – Account name or index (default: default account).

Returns:

Example:

[
    {
        "name": "INBOX",
        "flags": "\\Noinferiors",
        "delimiter": "/"
    },
    {
        "name": "Archive",
        "flags": "\\Noinferiors",
        "delimiter": "/"
    },
    {
        "name": "Spam",
        "flags": "\\Noinferiors",
        "delimiter": "/"
    }
]

get_message(id: int, folder: str = 'INBOX', account: str | int | Account | None = None, with_body: bool = True) Mail[source]#

Get the full content of a message given the ID returned by search().

Parameters:
  • id – Message ID.

  • folder – Folder name (default: INBOX).

  • account – Account name or index (default: default account).

  • with_body – If set then the body/payload will be included in the response (default: True).

Returns:

A message in the same format as search(), with an added payload attribute containing the body/payload. Example response:

{
  "id": 123,
  "date": "2024-01-13T21:04:50",
  "size": 3833,
  "from": {
    "you@example.com": {
      "name": "Me",
      "route": null,
      "email": "you@example.com"
    }
  },
  "to": {
    "me@example.com": {
      "name": "Me",
      "route": null,
      "email": "me@example.com"
    }
  },
  "cc": {
    "they@example.com": {
      "name": "They",
      "route": null,
      "email": "they@example.com"
    }
  },
  "bcc": {
    "boss@example.com": {
      "name": "Boss",
      "route": null,
      "email": "boss@example.com"
    }
  },
  "subject": "Test email",
  "content": {
    "headers": {
      "Return-Path": "<you@example.com>",
      "Delivered-To": "me@example.com",
      "Date": "Sat, 13 Jan 2024 20:04:50 +0000",
      "To": "Me <me@example.com>",
      "Cc": "They <they@example.com>",
      "Bcc": "Boss <boss@example.com",
      "From": "You <you@example.com>",
      "Subject": "Test email",
      "Message-ID": "<0123456789@client>",
      "MIME-Version": "1.0",
      "Content-Type": "multipart/mixed;\r\n boundary=\"0123456789\""
    },
    "body": "This is the email body",
    "attachments": [
      {
        "filename": "signature.asc",
        "headers": {
          "Content-Type": "application/pgp-signature; name=signature.asc",
          "Content-Transfer-Encoding": "base64",
          "Content-Disposition": "attachment; filename=signature.asc"
        },
        "body": "-----BEGIN PGP SIGNATURE-----\r\n\r\n....\r\n\r\n-----END PGP SIGNATURE-----\r\n"
      },
      {
        "filename": "image.jpg",
        "body": "/9j/4gIcSUNDX1BST0ZJTEUAA...",
        "headers": {
          "Content-Type": "image/jpeg; Name=\"image.jpg\"",
          "MIME-Version": "1.0",
          "Content-Transfer-Encoding": "base64",
          "Content-Disposition": "attachment; filename=\"profile_pic.jpg\""
        }
      }
    ]
  },
  "seq": 123,
  "internal_date": "2024-01-13T21:05:12",
  "message_id": "<0123456789@client>",
  "reply_to": {
    "you@example.com": {
      "name": "You",
      "route": null,
      "email": "you@example.com"
    }
  },
  "sender": {
    "you@example.com": {
      "name": "You",
      "route": null,
      "email": "you@example.com"
    }
  }
}

get_messages(ids: Collection[int], folder: str = 'INBOX', account: str | int | Account | None = None, with_body: bool = True) Dict[int, Mail][source]#

Get the full content of a list of messages given their IDs returned by search().

Parameters:
  • ids – IDs of the messages to retrieve.

  • folder – Folder name (default: INBOX).

  • account – Account name or index (default: default account).

  • with_body – If set then the body/payload will be included in the response (default: True).

Returns:

A dictionary in the format {id -> msg}, where msg is in the same format as search(), with an added payload attribute containing the body/payload. See get_message() for an example message format.

get_sub_folders(folder: str = '', pattern: str = '*', account: str | int | Account | None = None) List[Dict[str, str]][source]#

Get the list of all the sub-folders hosted on the server or those matching a pattern.

Parameters:
  • folder – Base folder (default: root).

  • pattern – Pattern to search (default: None).

  • account – Account name or index (default: default account).

Returns:

Example:

[
    {
        "name": "INBOX",
        "flags": "\\Noinferiors",
        "delimiter": "/"
    },
    {
        "name": "Archive",
        "flags": "\\Noinferiors",
        "delimiter": "/"
    },
    {
        "name": "Spam",
        "flags": "\\Noinferiors",
        "delimiter": "/"
    }
]

main()[source]#

Implementation of the main loop of the plugin.

move_messages(messages: List[int], destination: str, source: str = 'INBOX', account: str | int | Account | None = None)[source]#

Move a set of messages IDs from a folder to another.

Parameters:
  • messages – List of message IDs.

  • source – Source folder.

  • destination – Destination folder.

  • account – Account name or index (default: default account).

remove_flags(messages: List[int], flags: str | List[str], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Remove a set of flags to the specified set of message IDs.

Parameters:
  • messages – List of message IDs.

  • flags

    List of flags to be added. Examples:

    ['Flagged']
    ['Seen', 'Deleted']
    ['Junk']
    

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

rename_folder(old_name: str, new_name: str, account: str | int | Account | None = None)[source]#

Rename a folder on the server.

Parameters:
  • old_name – Previous name

  • new_name – New name

  • account – Account name or index (default: default account).

restore_messages(messages: List[int], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Remove the Deleted flag from the specified set of message IDs.

Parameters:
  • messages – List of message IDs.

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

search(criteria: str | List[str] = 'ALL', folder: str = 'INBOX', attributes: List[str] | None = None, account: str | int | Account | None = None) List[Mail][source]#

Search for messages on the server that fit the specified criteria.

If no criteria is specified, then all the messages in the folder will be returned.

Parameters:
  • criteria

    It should be a sequence of one or more criteria items. Each criterion item may be either unicode or bytes (default: ALL). Example values:

    ['UNSEEN']
    ['FROM', 'me@example.com']
    ['TO', 'me@example.com']
    ['SMALLER', 500]
    ['NOT', 'DELETED']
    ['TEXT', 'foo bar', 'FLAGGED', 'SUBJECT', 'baz']
    ['SINCE', '2020-03-14T12:13:45+00:00']
    

    It is also possible (but not recommended) to pass the combined criteria as a single string. In this case IMAPClient won’t perform quoting, allowing lower-level specification of criteria. Examples of this style:

    'UNSEEN'
    'SMALLER 500'
    'NOT DELETED'
    'TEXT "foo bar" FLAGGED SUBJECT "baz"'
    'SINCE 03-Apr-2005'
    

    To support complex search expressions, criteria lists can be nested. The following will match messages that are both not flagged and do not have “foo” in the subject:

    ['NOT', ['SUBJECT', 'foo', 'FLAGGED']]
    

    See RFC 3501#section-6.4.4 for more details.

  • folder – Folder to search (default: INBOX).

  • attributes – Attributes that should be retrieved, according to RFC 3501 (default: ALL = [FLAGS INTERNALDATE RFC822.SIZE ENVELOPE]). Note that BODY will be ignored if specified here for performance reasons - use get_message() if you want to get the full content of a message known its ID from search().

  • account – Account name or index (default: default account).

Returns:

List of messages matching the criteria. Example:

[
  {
    "id": 702,
    "seq": 671,
    "flags": [
      "nonjunk"
    ],
    "internal_date": "2020-08-30T00:31:52+00:00",
    "size": 2908738,
    "bcc": {},
    "cc": {},
    "date": "2020-08-30T00:31:52+00:00",
    "from": {
      "test123@gmail.com": {
        "name": "A test",
        "route": null,
        "email": "test123@gmail.com"
      }
    },
    "message_id": "<SOMETHING@mail.gmail.com>",
    "in_reply_to": "<SOMETHING@mail.gmail.com>",
    "reply_to": {},
    "sender": {
      "test123@gmail.com": {
        "name": "A test",
        "route": null,
        "email": "test123@gmail.com"
      }
    },
    "subject": "Test email",
    "to": {
      "me@gmail.com": {
        "name": null,
        "route": null,
        "email": "me@gmail.com"
      }
    }
  }
]
search_flagged_messages(folder: str = 'INBOX', account: str | int | Account | None = None) List[Mail][source]#

Shortcut for search() that returns only the flagged/starred messages.

search_starred_messages(folder: str = 'INBOX', account: str | int | Account | None = None) List[Mail][source]#

Shortcut for search() that returns only the starred messages.

search_unseen_messages(folder: str = 'INBOX', account: str | int | Account | None = None) List[Mail][source]#

Shortcut for search() that returns only the unread messages.

send(to: str | List[str], from_: str | None = None, cc: str | List[str] | None = None, bcc: str | List[str] | None = None, subject: str = '', body: str = '', body_type: str = 'plain', attachments: List[str] | None = None, headers: Dict[str, str] | None = None, account: str | int | Account | None = None, **kwargs)[source]#

Send an email through the specified SMTP sender.

Parameters:
  • to – Receiver(s), as comma-separated strings or list.

  • from – Sender email address (from is also supported).

  • cc – Carbon-copy addresses, as comma-separated strings or list

  • bcc – Blind carbon-copy addresses, as comma-separated strings or list

  • subject – Mail subject.

  • body – Mail body.

  • body_type – Mail body type, as a subtype of text/ (e.g. html) (default: plain).

  • attachments – List of attachment files to send.

  • headers – Key-value map of headers to be added.

  • account – Account name/index to be used (default: default account).

set_flags(messages: List[int], flags: str | List[str], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Set a set of flags to the specified set of message IDs.

Parameters:
  • messages – List of message IDs.

  • flags

    List of flags to be added. Examples:

    ['Flagged']
    ['Seen', 'Deleted']
    ['Junk']
    

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

sort(folder: str = 'INBOX', sort_criteria: str | List[str] = 'ARRIVAL', criteria: str | List[str] = 'ALL', account: str | int | Account | None = None) List[int][source]#

Return a list of message ids from the currently selected folder, sorted by sort_criteria and optionally filtered by criteria. Note that SORT is an extension to the IMAP4 standard, so it may not be supported by all IMAP servers.

Parameters:
  • folder – Folder to be searched (default: INBOX).

  • sort_criteria

    It may be a sequence of strings or a single string. IMAPClient will take care any required conversions. Valid sort_criteria values:

    .. code-block:: python
    
      ['ARRIVAL']
      ['SUBJECT', 'ARRIVAL']
      'ARRIVAL'
      'REVERSE SIZE'
    

  • criteria – Optional filter for the messages, as specified in search().

  • account – Account name or index (default: default account).

Returns:

A list of message IDs that fit the criteria.

start()#

Start the plugin.

stop()#

Stop the plugin.

unflag_message(message: int, folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Remove a flag/star from the specified set of message ID.

Parameters:
  • message – Message ID.

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

unflag_messages(messages: List[int], folder: str = 'INBOX', account: str | int | Account | None = None)[source]#

Remove a flag/star from the specified set of message IDs.

Parameters:
  • messages – List of message IDs.

  • folder – IMAP folder (default: INBOX).

  • account – Account name or index (default: default account).

wait_stop(timeout=None)#

Wait until a stop event is received.