π£ Discord Webhook
Mirrors mail activity into a Discord channel, so staff can watch the post without opening a menu.
Off by default. It needs no plugin β just a webhook URL.
Setup
- In Discord: Channel settings β Integrations β Webhooks β New Webhook, then copy its URL.
- In
config.yml:
discord:
enabled: true
webhook-url: "https://discord.com/api/webhooks/..."
flush-seconds: 5
events:
- SENT
- SENT_SERVER
- CLAIMED
- DISMISSED
- RETURNED
- EXPIRED
- ADMIN_CLAIMED
- ADMIN_DELETED
The bot's name and avatar are fixed, and the stripe colour comes from the event. Only the URL, the window and the event list are yours to set.
/mail reload.
The URL must be https://. Anything else is refused with a warning rather than sent.
Events
Every event is listed by default. Remove any you do not want to see.
| Event | Fires when |
|---|---|
SENT | A player sent mail to another player |
SENT_SERVER | Server mail was queued |
CLAIMED | A mail was claimed |
DISMISSED | A player threw a receipt away |
RETURNED | Unclaimed mail bounced back to its sender |
EXPIRED | Unclaimed mail was destroyed |
ADMIN_CLAIMED | Staff took a copy through /mail admin |
ADMIN_DELETED | Staff deleted a mail permanently |
The last two are the ones worth keeping on a server with several staff members: they are the only actions that create items or destroy them irreversibly.
What a post contains
Each mail becomes one embed with everything it was carrying:
π¨ Mail sent
βοΈ A little help
Here, you'll need this more than me. Good luck out there.
π€ From π₯ To
Anonymous (Steve) Alex
π° Items
16Γ Bread
1Γ Diamond Sword
πͺ Money
250.00
π§ Staff
Notch
| Field | Notes |
|---|---|
| Subject | The heading; the letter itself is its value |
| From | The sender. Server mail is marked (server) |
| To | The recipient, or a count β see below |
| Items | Every attachment with its amount, up to twelve lines |
| Money | Only shown when there is some |
| Staff | Only on administrative events β see below |
A mail with no written message reads no message under its subject.
The Staff field
It appears on SENT_SERVER, ADMIN_CLAIMED and ADMIN_DELETED, and nowhere else β the three
events a player cannot cause on their own mailbox.
That rule is the action, not "was somebody involved". Every claim has somebody involved: the recipient. Naming them under Staff would read as a player moderating themselves.
Server mail sent from console is credited to Console; sent by an admin, to their name.
Anonymous mail is unmasked, exactly as in /mail admin: the channel shows
Anonymous (Steve). Anonymity is a promise to the recipient, not to the staff channel.
Colours
The stripe is not configurable, because it carries meaning. Scanning a busy channel, the only distinction worth a colour is what the event did:
| Colour | Means | Events |
|---|---|---|
π’ #87d137 | Finished cleanly | SENT CLAIMED |
π£ #9f69ff | The server or its staff acted | SENT_SERVER ADMIN_CLAIMED |
π‘ #ffbc2e | Nothing lost, worth a look | DISMISSED RETURNED |
π΄ #df3752 | Something was destroyed | EXPIRED ADMIN_DELETED |
Everything a player typed β subject, letter, names β is escaped for both JSON and Discord markdown, so a subject full of asterisks and backticks arrives as the characters somebody typed rather than as formatting.
Recipients, and why broadcasts show a number
| Sent to | To field reads |
|---|---|
| One player | Their name |
server:all / server:online | 412 players |
A broadcast is one letter delivered to many mailboxes, so listing four hundred names would bury the mail itself and tell you nothing you did not already know from the command. The count is the useful part.
Why posts are grouped
flush-seconds is not a delay for its own sake. Everything inside a window becomes one message,
grouped by the mail rather than by the event β which is exactly what makes the detail above
affordable.
A server:all broadcast records one event per recipient. On a server with a thousand known
players, one command is a thousand events, against a webhook Discord limits to roughly thirty
requests a minute. Sent individually they would be rate-limited within seconds, and most of what
you wanted to see would be the part that got dropped.
Because the grouping is on content, that whole broadcast collapses into a single embed carrying the full letter, with the audience as a count. Names are only looked up where one will actually be printed, so a thousand-player broadcast costs no name lookups at all.
Raise flush-seconds if Discord ever rate-limits you; the plugin says so in console when it does.
What it will not do
- It never blocks the server. Posting is asynchronous, and a queue that fills up drops events with a console warning rather than growing without limit. An unreachable Discord must never become a laggy Minecraft server.
- It is independent of the transfer log.
log.enabled: falsesilences the database log and leaves the webhook running, and the reverse works too. They answer different questions. - Player text cannot restyle the post. Subjects are escaped for both JSON and Discord markdown, so a subject full of backticks and asterisks arrives as the characters somebody typed.