Context plug-ins¶
Context plug-ins extend or override context variables passed to templates.
You may have an arbitrary number of context plug-ins, e.g. to load information about billing, account status, support tickets etc.
Each context plug-in can indicate whether it should be loaded based on the content of the current context. This enables them to “fire” based on the event being notified, or the recipient, or more.
Note
The class for context plugins was renamed in Tattler version 1.2.0 .
Up until Tattler version 1.1.1 you would inherit from class
ContextTattlerPlugin in order to define a context plug-in.
Since Tattler version 1.2.0, the class was renamed to
ContextPlugin
for simplicity and symmetry with
Addressbook plug-ins.
Name ContextTattlerPlugin is still available as an alias for
backward compatibility, but you’ll get a deprecation notice when
plug-ins inheriting from it are loaded.
Writing a context plug-in¶
Context plug-ins are python files that
are placed in the plug-in directory,
implement the
ContextPlugininterface of classtattler.server.pluginloader.ContextPlugin.
Plug-in filenames must end with _tattler_plugin.py; other filenames are ignored.
To create a context plug-in:
Familiarize yourself using the quickstart example.
Start coding your own starting with the sample plug-ins in Tattler’s repository.
See Deploying plug-ins for tips on deployment.
Supplying attachments¶
A context plug-in can attach files (inline images, PDFs, etc.) to outgoing emails by
populating the reserved _attachments context key. The shape is the same as the
HTTP wire format, with one
plug-in-only convenience: payloads can be passed as raw bytes via content_bytes
instead of base64 strings.
from tattler.server.pluginloader import ContextPlugin
class BrandingTattlerPlugin(ContextPlugin):
def process(self, context):
attachments = dict(context.get('_attachments', {}))
# inline image -- key is the cid (must contain '@')
attachments['logo@brand'] = {
'content_bytes': self._load_logo_bytes(),
}
# regular attachment -- key is the filename
attachments['terms.pdf'] = {
'url': 'https://internal/legal/terms.pdf',
}
context['_attachments'] = attachments
return context
A few things to know:
Disambiguation by key shape. A key containing
@is the Content-ID of an inline image, referenced from HTML as<img src="cid:logo@brand">. A key without@is the filename of a regular attachment, and the file extension drives the MIME type (so use real filenames likeinvoice.pdf, notfile1).Pipelining. When several context plug-ins are configured, a later plug-in sees the attachments accumulated by earlier plug-ins. Always copy the dict before mutating it (
dict(context.get('_attachments', {}))) so you don’t accidentally mutate state owned by a sibling plug-in.Type detection for inline images. Tattler auto-detects PNG, JPEG, GIF, WebP, and SVG from the bytes. You don’t (and can’t) supply a
filenamefor inline entries; if your bytes aren’t one of those formats, the notification fails with a clear error.Size limit. The total raw size of attachments per email is capped at 7 MB. Plug-ins hitting the cap should consider linking to the file from the email body instead.