By Sarah Martinez · Published August 20, 2026 · Updated August 20, 2026 · 6 min read
Quick Answer: An email-to-fax API converts an outgoing email into a fax transmission. Address the email to
{fax_number}@{provider_gateway_domain}, attach your PDF, and the provider dials and transmits. Any language that can send SMTP email can send a fax this way.
An email-to-fax API is the fastest way to bolt fax sending onto an application that already has email infrastructure. Rather than integrating a new REST client, your code composes an email to a special gateway address, attaches the document to fax, and lets the provider handle the PSTN side. The recipient sees a normal fax; your app never touches a fax protocol.
This approach is common in legacy systems, EHR integrations, and rapid prototypes — anywhere SMTP is already wired up and adding another HTTP dependency feels heavyweight. If you're considering this route or evaluating it against a full REST fax API, this guide walks through how email fax gateways work, how to send one from Python, Node.js, and PHP, and where the approach breaks down.
How Email-to-Fax Gateways Work
An email fax gateway is a mail server that listens for specially addressed messages, strips the attachment, and hands it off to the PSTN fax network. The flow:
- Your application authenticates with the provider's SMTP server.
- You send an email to
{fax_number}@{gateway_domain}with a PDF attachment. - The gateway validates your account, extracts the attachment, and converts it to a fax signal.
- The gateway dials the recipient's fax machine or cloud fax number.
- Delivery confirmation (or failure notice) arrives as a reply email to the sender address.
The recipient's phone number is embedded in the To address. The subject line and email body are typically ignored — a few providers use the subject as the cover page message.
Authentication varies by provider
Some providers authenticate by SMTP credentials (username + password). Others tie your sending address to your account — any email from a registered address is accepted without a password. Check your provider's setup guide before writing code.
Recipient Address Format
The fax number goes in the To field, formatted as an email address. Most providers follow one of two conventions:
| Country | Format | Example |
|---|---|---|
| US & Canada | {10-digit-number}@gateway.provider.com | 15551234567@fax.provider.com |
| International | {countrycode}{number}@gateway.provider.com | 441134567890@fax.provider.com |
| With cover note | {number}+{subject}@gateway.provider.com | 15551234567+Contract@fax.provider.com |
Always use the full number including area code and, for international, the country code without the leading +. Formatting errors produce silent delivery failures on many platforms.
Step-by-Step: Send a Fax via Email
Choose a provider and get SMTP credentials
Sign up for a service that supports email-to-fax (InterFax, Fax.com, eFax, and several others offer this). Retrieve the SMTP host, port (usually 465 or 587), your username, and your account API key or password. Note the gateway domain for the recipient address.
Prepare your PDF
Convert your document to PDF before sending. PDF is accepted by every provider and preserves layout exactly. Other formats like DOCX or TIFF are supported by some gateways, but PDF is the safest universal choice.
Compose the email
Set To to {fax_number}@{gateway_domain}, attach the PDF, and leave the body empty or include a short cover note (provider-dependent). Do not embed additional recipients in CC or BCC — most gateways reject multi-recipient emails.
Send via authenticated SMTP
Use your language's SMTP library with TLS enabled. See the code examples below.
Check delivery via reply email
The gateway sends a reply to your From address confirming delivery or reporting a failure. In a production system, point your From address at a mailbox your app can read programmatically, or use a provider that also exposes a REST status endpoint.
Code Examples
Python
Python's built-in smtplib handles everything without third-party libraries.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
def send_fax_by_email(
fax_number: str,
pdf_path: str,
smtp_host: str,
smtp_user: str,
smtp_pass: str,
gateway_domain: str,
) -> None:
msg = MIMEMultipart()
msg['From'] = smtp_user
msg['To'] = f'{fax_number}@{gateway_domain}'
msg['Subject'] = 'Fax Transmission'
with open(pdf_path, 'rb') as f:
part = MIMEBase('application', 'pdf')
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename='document.pdf')
msg.attach(part)
with smtplib.SMTP_SSL(smtp_host, 465) as server:
server.login(smtp_user, smtp_pass)
server.send_message(msg)
print(f'Fax queued to {fax_number}')
send_fax_by_email(
fax_number='15551234567',
pdf_path='./contract.pdf',
smtp_host='smtp.yourprovider.com',
smtp_user='you@company.com',
smtp_pass='your-api-key',
gateway_domain='fax.yourprovider.com',
)
Node.js (nodemailer)
const nodemailer = require('nodemailer');
const fs = require('fs');
async function sendFaxByEmail(faxNumber, pdfPath, config) {
const transporter = nodemailer.createTransport({
host: config.smtpHost,
port: 465,
secure: true,
auth: { user: config.user, pass: config.pass },
});
await transporter.sendMail({
from: config.user,
to: `${faxNumber}@${config.gatewayDomain}`,
subject: 'Fax Transmission',
attachments: [
{
filename: 'document.pdf',
content: fs.readFileSync(pdfPath),
contentType: 'application/pdf',
},
],
});
console.log(`Fax queued to ${faxNumber}`);
}
sendFaxByEmail('15551234567', './contract.pdf', {
smtpHost: 'smtp.yourprovider.com',
user: 'you@company.com',
pass: 'your-api-key',
gatewayDomain: 'fax.yourprovider.com',
}).catch(console.error);
PHP (PHPMailer)
<?php
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
function sendFaxByEmail(
string $faxNumber,
string $pdfPath,
string $smtpHost,
string $smtpUser,
string $smtpPass,
string $gatewayDomain
): void {
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = $smtpHost;
$mail->SMTPAuth = true;
$mail->Username = $smtpUser;
$mail->Password = $smtpPass;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
$mail->setFrom($smtpUser);
$mail->addAddress("{$faxNumber}@{$gatewayDomain}");
$mail->Subject = 'Fax Transmission';
$mail->Body = '';
$mail->addAttachment($pdfPath, 'document.pdf');
$mail->send();
}
sendFaxByEmail(
'15551234567',
'./contract.pdf',
'smtp.yourprovider.com',
'you@company.com',
'your-api-key',
'fax.yourprovider.com'
);
Always use TLS
Send over SMTP_SSL (port 465) or STARTTLS (port 587). Unencrypted SMTP on port 25 exposes document contents in transit and disqualifies the integration from HIPAA compliance.
Limitations of Email-to-Fax
Email gateways are fast to set up but introduce friction in production systems.
No real-time delivery status. The gateway sends a reply email when a fax succeeds or fails. Parsing an inbox in application code — handling threading, HTML formatting, encoding — is fragile. REST APIs return a status field you can poll or receive via webhook.
No structured error codes. A failure email says something like "your fax to 15551234567 was not delivered" without machine-readable detail. REST APIs return codes like user_busy, no_answer, and no_fax_signal that your retry logic can act on. See the send fax API guide for how that looks in practice.
SMTP delivery is not guaranteed. If your SMTP connection drops mid-send or the gateway's mail server is temporarily down, the fax silently disappears. REST APIs return an HTTP error you can catch and retry immediately.
HIPAA requires extra care. Email infrastructure adds another hop to audit. The gateway provider must sign a BAA, and your SMTP path must be TLS-encrypted end-to-end. Many generic email-to-fax services do not meet this bar. See our HIPAA fax API guide for what a compliant integration requires.
Subject and body support is inconsistent. Some gateways strip everything but the attachment; others include the subject as a cover page note. Document this behavior for every provider you use.
Email Gateway vs REST API: Which to Choose
| Email-to-Fax Gateway | REST API (e.g., mFax) | |
|---|---|---|
| Integration effort | Low — reuse existing SMTP | Medium — one HTTP client |
| Delivery status | Reply email (async, fragile) | Webhook + polling (structured) |
| Error codes | Free-text email | Machine-readable codes |
| Retry on failure | Manual / email bounce handling | Built-in retry with failure reason |
| Volume | Low–medium | Any |
| Inbound faxes | Provider-dependent | Yes (webhook + list API) |
| HIPAA-ready | Varies — BAA not guaranteed | Yes, with signed BAA |
| Latency to first status | Minutes (email round-trip) | Seconds (webhook) |
Choose email-to-fax when you're building a one-off internal tool, prototyping, or integrating with a legacy system where SMTP is already the only outbound channel.
Choose a REST API when you need reliable delivery tracking, volume above a few hundred faxes per day, HIPAA compliance, or automatic retry on failure.
The REST API Alternative: mFax
The mFax API is a first-party REST API purpose-built for programmatic faxing. It solves every limitation listed above.
A single authenticated POST /v1/faxes with two fields — to (the recipient in E.164) and file (your PDF) — queues the fax and returns a uuid. You track delivery by polling GET /v1/faxes/{uuid} or by receiving a fax.delivered or fax.failed webhook to your endpoint.
curl -s -X POST https://developers.mfax.to/v1/faxes \
-H "Authorization: Bearer zk_live_your_key_here" \
-F "to=+15551234567" \
-F "file=@./contract.pdf"
Response:
{
"uuid": "f3a9b812-...",
"status": "queued",
"to": "+15551234567"
}
Status lifecycle: queued → sending → delivered | failed. On failure the response includes a failure_reason field (user_busy, no_answer, no_fax_signal, number_out_of_service) so your retry logic can distinguish a busy line from a disconnected number.
mFax API is included with every mFax Business plan, which also provides a signed BAA, AES-256 encryption at rest, TLS 1.2+ in transit, and SOC 2 Type II compliance. Plans start from about $9/mo and let you build your own seat and page count using the live calculator.
Full API reference
Read the endpoint spec, request/response schemas, webhook signing, and error codes at developers.mfax.to.
Start Building
Email-to-fax gateways are the quickest way to add fax sending to an existing email-capable application. Point your SMTP client at the provider's gateway domain, address the email to {fax_number}@{domain}, attach a PDF, and the provider handles the rest.
For production use, consider the mFax REST API instead: create an API key in the mFax dashboard, read the reference at developers.mfax.to, and get real-time webhooks, structured errors, and HIPAA-ready compliance from the start.