Mail printed letters from ERPNext with PostGrid
Install postgrid_integration, mail any print format as a physical letter, automate mailings with Notifications, and understand test keys, live keys and limits.
On this page
This document shows how to turn any ERPNext or Frappe print format into a physical letter using the postgrid_integration app and PostGrid's Print & Mail service. Use it when invoices, statements or notices need to go out on paper, either by hand from the print view or automatically from a Notification.
The app renders the print format to a PDF, hands it to PostGrid, and records the letter on the document's timeline. PostGrid prints, stuffs and posts it. If the document only needs a signature, eSign collects one electronically with no paper involved.
Before you start
You need three things:
A PostGrid Print & Mail account and its API keys. Keys live in the PostGrid dashboard under settings.
Python 3.10 or newer on the bench. The app uses
matchstatements.A site that PostGrid can reach over the public internet, if you want delivery status to flow back into ERPNext. See Delivery status and webhooks.
Every document you mail needs a sender address and a recipient address, both stored as Frappe Address records. Each address must have a country, because the app looks up the country code and sends it to PostGrid.
Install the app
Run these from the bench directory, as the bench user:
bench get-app avunu/postgrid_integration
bench --site <SITE_NAME> install-app postgrid_integrationThe app depends on postgrid-python, pyjwt and pypdf, which bench installs with it.
Warning
The app's manifest does not pin postgrid-python, and the code calls the library's older module-level API (postgrid.pm_key, client.Letter, client.Webhook). Release 1.0.14, the last of the 1.x line, has those names. Releases from 2.0.0 on, including 2.3.0, replaced them with a generated PostGrid client and have none of them. If saving PostGrid Settings fails with an AttributeError after a fresh install, check which postgrid-python version bench resolved. We did not run the app against either version, so test a pin to the 1.x line in a staging bench before you rely on it.
Installing does two things for you. It adds a PostGrid Settings link under a "Direct Mail" card on the Integrations workspace, and on every bench migrate it adds Mailed Letter as an option to the Notification channel field and the Communication communication_type field.
Uninstalling removes the workspace link and reverts those two field options.
Configure PostGrid Settings
Open PostGrid Settings. It is a single doctype, and only users with the System Manager role can see it.
Paste your test key into Test API Key and, when you are ready to mail for real, your live key into Live API Key.
Set Mode to
TestorLive. A new settings form starts onTest, the first option in the list.Set the default options (see the table below).
Save.
On save, the app registers a webhook with PostGrid for the selected mode and generates a shared secret. The secret and webhook IDs are hidden fields. You do not copy them anywhere.
| Setting | What it does |
|---|---|
| Address Placement | Insert Blank Page adds a page at the front for the recipient address. Top of First Page prints it on your first page, so leave room for it in the print format. |
| Envelope Type | Standard Double Window or Flat. |
| Color | Print in color instead of black and white. |
| Double Sided | Print on both sides of the sheet. |
| Express | Ask PostGrid for express delivery. |
| Update Addresses | Writes PostGrid's verified address back to the Frappe Address. |
| Save PDF Files | Keeps PostGrid's final PDF as a private file on the letter's timeline entry. |
These defaults pre-fill the Mail dialog and the Notification fields. You can override them on each letter.
Test keys and live keys
The app keeps one key per mode and uses the one that matches Mode. Changing Mode is the only switch between them. Nothing else in the app differs.
Start in Test while you tune the print format and address placement. What PostGrid does with a test-mode letter, for example whether it is printed or posted, is decided by PostGrid, not by this app. Read PostGrid's own documentation for that before you assume anything.
When you switch to Live and save, the app registers a second webhook for that mode if it has none. From then on the app sends letters with your live key, so send yourself a test-mode letter first and confirm the print format and addresses look right.
Mail a document by hand
Open a submitted document, for example a Sales Invoice, and open its print view.
Pick the print format you want to send in the print view's format selector. The Mail button sends whichever format is selected.
Click the Mail button at the top of the print view.
Fill in the Mail Letter dialog and click Mail via PostGrid.
The dialog asks for:
From Address (required). It defaults to the document's
company_address, or, when ERPNext is installed, to the company's default address.To Address (required). It defaults to the first of
customer_address,shipping_address,billing_address,supplier_addressoraddressthat the document has.To Contact (optional). It defaults to
contact_person. The contact's first and last name go on the envelope.Address Placement, Envelope Type and Additional Options (double sided, color, express), pre-filled from your settings.
With Cover Letter and Cover Letter Print Format. The cover letter is another print format for the same doctype, rendered for the same document. It goes in front of the main letter, and when Double Sided is on, the app inserts a blank page between the two.
You get an alert with a link to the Integration Request when PostGrid accepts the letter, or a red alert with a link to the failed request when it does not.
Note
The Mail button does not appear on drafts. The app skips any document whose docstatus is 0, which also means doctypes that are not submittable never show it. Use a Notification (below) or submit the document first.
What gets recorded
Each mailing creates:
An Integration Request for the service
PostGrid, holding the request and the response, with statusQueued, orFailedwith the error.A Communication of type
Mailed Letterlinked to your document, with a subject of<DOCNAME> Direct Mail.A timeline card on the document, titled "Letter mailed to ...". It has a status pill, a link to the saved PDF when you enabled Save PDF Files, and an Open in PostGrid menu item that goes to the letter in the PostGrid dashboard.
The app also stores PostGrid's contact ID on both Address records, in a hidden postgrid_id field it adds to Address.
Automate mailings with Notifications
The app adds a Mailed Letter channel to the core Notification doctype. Create a Notification the same way you would for email, then choose Channel Mailed Letter.
Set Document Type and Event. In the code we read, these events fire:
New,Save,Submit,Cancel,Days BeforeandDays After. The app does not hook the document's change event, soValue Changedoes not mail anything, andMethodonly fires for theafter_insert,on_update,on_submitandon_cancelmethods. We did not test the events on a live site.Add a Condition to limit which documents mail.
Choose the Print Format to send. The app turns on attach-print for you and hides that checkbox.
In Direct Mail Settings, set From Address. It defaults to your company's default address when ERPNext is installed.
Set To Address Field, a dropdown listing every Link-to-Address field on the document type. This field is required.
Set the layout options: Address Placement, Envelope Type (required), Color, Double Sided, Express, and optionally With Cover Letter with a Cover Letter Print Format.
Recipients are not required for this channel. If you leave Message empty, the app fills in "See the attached document."
If the document's address field is empty when the Notification fires, no letter is sent and an Error Log entry titled "Failed to mail notification" is written. Any other failure while mailing is logged under the same title with the traceback.
Warning
A Notification mails every time its event fires. A Save event on a document that is edited often will send a letter on every save. Always add a Condition, such as a status or a "letter sent" checkbox that your own workflow sets, and use Submit or Days After where that fits.
Days Before and Days After events run from the daily scheduler, so the scheduler must be enabled on the site. The app skips all Notifications during imports with muted emails, patches and installs.
Known gap: To Contact Field
The Notification form has a To Contact Field, but in the code we read, mail_letter only takes the contact from the to_contact entry in the layout parameters. The Notification does not pass that entry, so the contact is not used and the envelope carries the address title as the company name only. We did not test this on a live bench. If you need a person's name on automated letters, put it in the Address title for now.
Delivery status and webhooks
PostGrid reports progress to a webhook on your site. The app creates it for you, and it listens for letter, postcard, cheque and return-envelope events. The endpoint is a guest-allowed method:
/api/method/postgrid_integration.postgrid_integration.doctype.postgrid_settings.webhooksEach call is a signed JWT (HS256) that the app verifies with the generated secret. A call with a bad signature is rejected with an authentication error.
The app maps PostGrid statuses to the Communication's delivery status and the Integration Request status:
| PostGrid status | Delivery status | Integration Request status |
|---|---|---|
ready | Scheduled | Queued |
printing | Sending | Authorized |
processed_for_delivery | Sent | Completed |
completed | Opened | Completed |
cancelled | Rejected | Cancelled |
Only these five statuses are mapped. A status outside this list is not handled by the code we read.
The webhook URL is built from your site's configured URL. PostGrid has to be able to call that URL. If your site is not reachable from the internet, expect the status updates, saved PDFs and address updates to be missing.
The settings form has a Reset Webhooks action that registers fresh webhooks for both Test and Live. It expects both keys to be set. The code does not delete older registrations and does not save the new webhook IDs on the form, so check the PostGrid dashboard for duplicates afterwards.
When Update Addresses is on, a webhook that carries a verified address updates the matching Frappe Address (street lines, city, state, postal code, and the title when a company name is returned). It only matches addresses that already have a postgrid_id, which is set by an earlier mailing.
Limits
Only letters work. The code for postcards and cheques is switched off in the app's
MAIL_TYPESlist, with a comment that it waits on those being implemented.The Mail button only appears for non-draft documents in the print view.
Both addresses need a country, and the app does not verify addresses itself. A bad address fails at PostGrid and shows up in the Integration Request.
A failed letter is not retried. Fix the cause and mail it again by hand.
Letters are built from the PDF that Frappe renders, so what you see in the print preview is what is sent. Keep your margins compatible with the Address Placement you chose.
The
sync_contactcode in the repository that would push Contacts to PostGrid is not hooked up. Its own comment says PostGrid's API does not support updating contacts.The app's version is
0.0.1, and it has no automated tests beyond an empty stub. Treat it as a small, useful tool, not a hardened product, and try each change on a staging site first.
Sources
This article is in the public domain (CC0 1.0), code samples included. Use it however helps you.