-
Notifications
You must be signed in to change notification settings - Fork 15
Email Signatures
Each analyst writes their own signatures, keeps as many as they need, and marks one as the default.
Set at your name β Preferences β Email signatures.
From discussion #80, released as update #1127.
There is no shared signature, no install-wide signature, and no administrator screen for other people's signatures. That is a decision, not an omission.
A signature is a person signing their own name. One signature for a whole team is either wrong for everybody, or it is filled in entirely by merge codes β at which point it is a template with a person's details poured into it, which is what this already is.
So every request is scoped to whoever is signed in, never to an id in the request body. Posting somebody else's signature id gets you nothing:
| Attempt | Result |
|---|---|
| Read another analyst's signatures | Only your own are returned |
| Overwrite one by id | "That signature does not exist." |
| Delete one by id |
deleted: false β nothing removed |
That last one is worth noting: it reports honestly that nothing was deleted rather than returning a cheerful success for an operation that did nothing.
The obvious objection to several signatures is that choosing one becomes a decision on every single reply, and on a busy desk that is a tax paid hundreds of times a day. Worse, the failure mode is picking the wrong one and sending the casual internal sign-off to a customer.
That is why exactly one is always the Default, and the default is used without asking. An analyst who only ever wants one signature never sees a choice; deviating is a deliberate act. Several signatures then cost nothing to the people who do not want them.
The cases that justify keeping more than one are real:
- Formal for customers, short for colleagues β the same person, two registers
- One per language β FreeITSM ships 24 locales, and an analyst who answers in two of them needs two sign-offs
- Per client company β an MSP analyst replying on behalf of different customers
Your first signature becomes the default whether or not you tick the box. Otherwise you create one signature, nothing is flagged, nothing is ever used, and the feature reads as broken.
Deleting the default does not leave you with none: the first remaining signature takes over. There is deliberately no second rule promoting a replacement at delete time β one rule, applied when the question is asked, cannot disagree with itself.
An analyst record held a name, an email address and a username. Nothing else. A "template driven" signature with only those two merge codes is barely worth templating β you could type them.
So job title, department, phone and mobile are now part of your account, edited in the same place, in a My details section.
They are stored on the analyst rather than borrowed from a person record. An analyst may have no person record at all, and a signature that silently loses its phone number because a link is missing is worse than one that never had it.
Your name and email address are not editable here. They identify the account, they are used to sign in and to address mail, and on an installation using LDAP or SSO they come from the directory β editing them locally would either be overwritten on the next sync or quietly diverge from it.
| Code | Fills in |
|---|---|
[my_name] |
Your full name |
[my_job_title] |
Your job title |
[my_department] |
Your department |
[my_email] |
Your email address |
[my_phone] |
Your phone number |
[my_mobile] |
Your mobile number |
FreeITSM's email templates have [analyst_name]. It resolves like this:
COALESCE(o.full_name, a.full_name) -- o = ticket owner, a = assigned analystThat is the ticket's owner or assignee β not the person typing. It is the right answer for an automatic email about a ticket, and the wrong answer for a signature: Sam answering a ticket owned by Jo would sign it Jo, every time, to the customer, and neither of them would notice.
So signatures have their own vocabulary tied to the signed-in analyst. The my_ prefix is the whole distinction, and it reads correctly next to the account screen these are edited on. [analyst_name] keeps meaning exactly what it always meant.
If you have not filled in a mobile number, [my_mobile] disappears rather than appearing literally. This is the opposite of what canned responses do with an unresolved code, and deliberately: an unresolved [requester_first_name] sits in an editor where an analyst reads it before sending, whereas an unfilled signature code would appear at the bottom of every email that person ever sends.
Note that surrounding punctuation is left alone. If you write [my_phone] | [my_mobile] and have no mobile, you get a trailing |. The preview shows you exactly that, so it is fixable β guessing at which separators to strip would be less predictable than showing you the truth.
The editor previews as you type, filling in your own details β including details you have typed into My details but not yet saved, so you can see a phone number take effect before committing to it.
The list of saved signatures also shows each one rendered, not raw. The point of the list is to see what actually goes out.
Nothing inserts a signature into a reply. This update is the manager: writing, storing and previewing them. Wiring the default one into the reply box is the next step, and the intended design is that it appears in the editor, visible and editable, rather than being stapled on invisibly when you press send β so that what the analyst sees is what the customer gets.
| File | Role |
|---|---|
includes/signatures.php |
renderSignature(), signatureMergeData(), defaultSignatureForAnalyst(), setDefaultSignature()
|
api/myaccount/get_signatures.php |
Signatures, profile and merge codes β session-scoped, no id input |
api/myaccount/save_signature.php |
Create/update; every statement paired with analyst_id
|
api/myaccount/delete_signature.php |
Delete, scoped the same way |
api/myaccount/save_profile.php |
Job title, department, phone, mobile |
system/preferences/index.php |
The UI, alongside the other personal settings |
analyst_signatures |
analyst_id, name, body, is_default, display_order
|
Three behaviours are load-bearing:
-
setDefaultSignature()clears every flag then sets one. Two statements, so "exactly one default" stays true even if an earlier write left two set. -
An empty body is judged on the text, not the markup. A cleared editor returns
<p> </p>, which is a truthy string and would otherwise save as an empty signature. -
A missing
analyst_signaturestable returns no signatures rather than raising β a part-upgraded install composes replies exactly as it did before, and never shows an error in the reply box.
- Limiting replies to particular senders β request 2 from the same discussion
-
The public web address β request 1, and
[ticket_url] - Email Send Log β where you can see what actually went out
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- Theming & Dark Mode
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
- MobileβFriendly
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- Problem Management
- Tasks
- Assets
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
- Forms
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)