Proofpoint Secure Email Relay Mail API
Project description
Proofpoint Secure Email Relay Mail API Python Library
This library implements all the functions of the SER Email Relay API via Python.
Requirements
- Python 3.9+
requestsrequests-oauth2clientpysocks- Active Proofpoint SER API credentials
Installing the Package
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
Features
- Send Emails: Easily compose and send emails with minimal code.
- Support for Attachments:
- Attach files from disk
- Encode attachments as Base64
- Send byte[] attachments
- Support for Inline HTML Content:
- Using the syntax
<img src="cid:logo"> - Content-ID can be set manually or auto-generated
- Using the syntax
- HTML & Plain Text Content: Supports both plain text and HTML email bodies.
- Recipient Management: Add
To,CC, andBCCrecipients with ease. - Reply Management: Add
Reply-Toaddresses to redirect replies.
Quick Start
import json
from ser_mail_api.v1 import *
if __name__ == "__main__":
# Default region when not specified is Region.US
client = Client("<client_id>", "<client_secret>", Region.US)
# 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)
Attachment MIME Type Deduction Behavior
When creating attachments, the library automatically attempts to determine the MIME type. This detection is based on:
- The
filenameargument when usingAttachment.from_bytesorAttachment.from_base64. - The
filepathwhen usingAttachment.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")
Inline Attachments and Content-IDs
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.
Using Dynamically Generated Content-ID
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__":
# Default region when not specified is Region.US
client = Client("<client_id>", "<client_secret>", Region.US)
# 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)
Setting a Custom Content-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__":
# Default region when not specified is Region.US
client = Client("<client_id>", "<client_secret>", Region.US)
# 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)
Proxy Support
Socks5 Proxy Example:
from ser_mail_api.v1 import *
if __name__ == '__main__':
# Default region when not specified is Region.US
client = Client("<client_id>", "<client_secret>", Region.US)
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__':
# Default region when not specified is Region.US
client = Client("<client_id>", "<client_secret>", Region.US)
credentials = "{}:{}@".format("proxyuser", "proxypass")
client._session.proxies = {'https': "{}://{}{}:{}".format('http', credentials, '<your_proxy>', '3128')}
HTTP Timeout Settings
from ser_mail_api.v1 import *
if __name__ == '__main__':
# Default region when not specified is Region.US
client = Client("<client_id>", "<client_secret>", Region.US)
# Timeout in seconds, connect timeout
client.timeout = 600
# Timeout advanced, connect / read timeout
client.timeout = (3.05, 27)
Known Issues
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.
Limitations
- The Proofpoint API currently does not support empty file attachments.
- If an empty file is sent, you will receive a 400 Bad Request error.
Additional Resources
For more information, refer to the official Proofpoint Secure Email Relay API documentation:
API Documentation
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ser_mail_api-2.0.6.tar.gz.
File metadata
- Download URL: ser_mail_api-2.0.6.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.23
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
524771ee3524838c0c32b5dab3a1fd0979cf37665df16f2b5d072e4a09565931
|
|
| MD5 |
0fa01e50c14c695784cbb39923329fa2
|
|
| BLAKE2b-256 |
9a264abf1df0626274acc8f413e48256c43348a338a8d928f7570bca051e5661
|
File details
Details for the file ser_mail_api-2.0.6-py3-none-any.whl.
File metadata
- Download URL: ser_mail_api-2.0.6-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.23
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b45b824f24a84a90ad891303f96fe073cd32c3f9721f55923738c33d352b20a1
|
|
| MD5 |
3ac277046e5e8b91ffba0c1bceeb4e7b
|
|
| BLAKE2b-256 |
d8389373e56fa10acce9ead2e9b96cb0ceb79a6277adeb961a484064de968130
|