
Security News
pnpm 10.12 Introduces Global Virtual Store and Expanded Version Catalogs
pnpm 10.12.1 introduces a global virtual store for faster installs and new options for managing dependencies with version catalogs.
This library implements all the functions of the SER Email Relay API via Python.
requests
requests-oauth2client
pysocks
You can install the tool using the following command directly from GitHub:
pip install git+https://github.com/pfptcommunity/ser-mail-api-python.git
Alternatively, you can install the tool using pip:
# Note: This may not work on Ubuntu 24.04:
pip install ser-mail-api
If you encounter an error similar to the following:
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
See /usr/share/doc/python3.12/README.venv for more information.
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
You should install pipx
or configure your own virtual environment and use the command referenced above:
pipx install ser-mail-api
<img src="cid:logo">
To
, CC
, and BCC
recipients with ease.Reply-To
addresses to redirect replies.import json
from ser_mail_api.v1 import *
if __name__ == "__main__":
client = Client("<client_id>", "<client_secret>")
# Create a new Message object
message = Message("This is a test email", MailUser("sender@example.com", "Joe Sender"))
# Add text content body
message.add_content(Content("This is a test message", ContentType.Text))
# Add HTML content body, with embedded image
message.add_content(Content("<b>This is a test message</b><br><img src=\"cid:logo\">", ContentType.Html))
# Create an inline attachment from disk and set the cid
message.add_attachment(Attachment.from_file("C:/temp/logo.png", Disposition.Inline, "logo"))
# Add recipients
message.add_to(MailUser("recipient1@example.com", "Recipient 1"))
message.add_to(MailUser("recipient2@example.com", "Recipient 2"))
# Add CC
message.add_cc(MailUser("cc1@example.com", "CC Recipient 1"))
message.add_cc(MailUser("cc2@example.com", "CC Recipient 2"))
# Add BCC
message.add_bcc(MailUser("bcc1@example.com", "BCC Recipient 1"))
message.add_bcc(MailUser("bcc2@example.com", "BCC Recipient 2"))
# Add attachments
message.add_attachment(Attachment.from_base64("VGhpcyBpcyBhIHRlc3Qh", "test.txt"))
message.add_attachment(Attachment.from_file("C:/temp/file.csv"))
message.add_attachment(Attachment.from_bytes(b"Sample bytes", "bytes.txt", "text/plain"))
# Set one or more Reply-To addresses
message.add_reply_to(MailUser("noreply@proofpoint.com", "No Reply"))
# Send the email
result = client.send(message)
print("HTTP Response: {}/{}".format(result.get_status(), result.get_reason()))
print("Reason:", result.reason)
print("Message ID:", result.message_id)
print("Request ID:", result.request_id)
When creating attachments, the library automatically attempts to determine the MIME type. This detection is based on:
filename
argument when using Attachment.from_bytes
or Attachment.from_base64
.filepath
when using Attachment.from_file
.If the MIME type cannot be determined, an exception will be raised.
from ser_mail_api.v1 import *
if __name__ == "__main__":
# Create an attachment from disk; the MIME type will be "application/vnd.ms-excel", and disposition will be "Disposition.Attachment"
Attachment.from_file("C:/temp/file.csv")
# This will throw an error, as the MIME type is unknown
Attachment.from_file("C:/temp/file.unknown")
# Create an attachment and specify the type information. The disposition will be "Disposition.Attachment", filename will be unknown.txt, and MIME type "text/plain"
Attachment.from_file("C:/temp/file.unknown", filename="unknown.txt")
# Create an attachment and specify the type information. The disposition will be "Disposition.Attachment", filename will be file.unknown, and MIME type "text/plain"
Attachment.from_file("C:/temp/file.unknown", mime_type="text/plain")
When creating attachments, they are Disposition.Attachment
by default. To properly reference a Content-ID (e.g.,
<img src="cid:logo">
), you must explicitly set the attachment disposition to Disposition.Inline
.
If the attachment type is set to Disposition.Inline
, a default unique Content-ID will be generated.
The example below demonstrates how to create inline content with a dynamically generated Content-ID inside an HTML message body.
from ser_mail_api.v1 import *
if __name__ == "__main__":
client = Client("<client_id>", "<client_secret>")
# Create a new Message object
message = Message("This is a test email", MailUser("sender@example.com", "Joe Sender"))
# Create an inline attachment with dynamically generated Content-ID
logo = Attachment.from_file("C:/temp/logo.png", Disposition.Inline)
# Add HTML content body, with embedded image
message.add_content(Content(f"<b>This is a test message</b><br><img src=\"cid:{logo.cid}\">", ContentType.Html))
# Add the attachment to the message
message.add_attachment(logo)
# Add recipients
message.add_to(MailUser("recipient1@example.com", "Recipient 1"))
# Send the email
result = client.send(message)
print("HTTP Response: {}/{}".format(result.get_status(), result.get_reason()))
print("Reason:", result.reason)
print("Message ID:", result.message_id)
print("Request ID:", result.request_id)
The example below demonstrates how to create inline content with a custom Content-ID inside an HTML message body.
from ser_mail_api.v1 import *
if __name__ == "__main__":
client = Client("<client_id>", "<client_secret>")
# Create a new Message object
message = Message("This is a test email", MailUser("sender@example.com", "Joe Sender"))
# Add an inline attachment with a custom Content-ID
message.add_attachment(Attachment.from_file("C:/temp/logo.png", Disposition.Inline, "logo"))
# Add HTML content body, with embedded image
message.add_content(Content(f"<b>This is a test message</b><br><img src=\"cid:logo\">", ContentType.Html))
# Add recipients
message.add_to(MailUser("recipient1@example.com", "Recipient 1"))
# Send the email
result = client.send(message)
print("HTTP Response: {}/{}".format(result.get_status(), result.get_reason()))
print("Reason:", result.reason)
print("Message ID:", result.message_id)
print("Request ID:", result.request_id)
Socks5 Proxy Example:
from ser_mail_api.v1 import *
if __name__ == '__main__':
client = Client("<client_id>", "<client_secret>")
credentials = "{}:{}@".format("proxyuser", "proxypass")
client._session.proxies = {'https': "{}://{}{}:{}".format('socks5', credentials, '<your_proxy>', '8128')}
HTTP Proxy Example (Squid):
from ser_mail_api.v1 import *
if __name__ == '__main__':
client = Client("<client_id>", "<client_secret>")
credentials = "{}:{}@".format("proxyuser", "proxypass")
client._session.proxies = {'https': "{}://{}{}:{}".format('http', credentials, '<your_proxy>', '3128')}
from ser_mail_api.v1 import *
if __name__ == '__main__':
client = Client("<client_id>", "<client_secret>")
# Timeout in seconds, connect timeout
client.timeout = 600
# Timeout advanced, connect / read timeout
client.timeout = (3.05, 27)
There is a known issue where empty file content results in a 400 Bad Request error.
{
"content": "",
"disposition": "attachment",
"filename": "empty.txt",
"id": "1ed38149-70b2-4476-84a1-83e73913d43c",
"type": "text/plain"
}
🔹 API Response:
Status Code: 400/BadRequest
Message ID:
Reason: attachments[0].content is required
Request ID: fe9a1acf60a20c9d90bed843f6530156
Raw JSON: {"request_id":"fe9a1acf60a20c9d90bed843f6530156","reason":"attachments[0].content is required"}
This issue has been reported to Proofpoint Product Management.
For more information, refer to the official Proofpoint Secure Email Relay API documentation:
API Documentation
FAQs
Proofpoint Secure Email Relay Mail API
We found that ser-mail-api demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
pnpm 10.12.1 introduces a global virtual store for faster installs and new options for managing dependencies with version catalogs.
Security News
Amaro 1.0 lays the groundwork for stable TypeScript support in Node.js, bringing official .ts loading closer to reality.
Research
A deceptive PyPI package posing as an Instagram growth tool collects user credentials and sends them to third-party bot services.