Plugins Directory » Redmine expert Helpdesk
|
|
Author: | Dennis Buehring |
|---|---|---|
| Website: | https://github.com/expertZentrale/redmine_expert_helpdesk | |
| Code repository: | https://github.com/expertZentrale/redmine_expert_helpdesk | |
| Registered on: | 2026-07-29 (25 days ago) | |
| Current version: | 0.4.0 | |
| Compatible with: | Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x | |
| User ratings: |
What it does¶
Turns mailboxes into a Redmine helpdesk. Incoming mail becomes a ticket, replies are matched onto the existing ticket, and agents answer the customer straight from the ticket page. Contacts, SLA tracking, phishing detection and a rules engine sit on top.
Reply matching is delegated to Redmine's own MailHandler, so In-Reply-To and [#id] subject patterns behave exactly as they do for Redmine's built-in mail handling, attachments included.
Mail providers¶
Each mailbox chooses its own backend:
- Microsoft 365 via the Microsoft Graph API (application-only).
- Generic IMAP/SMTP for Google Workspace, Exchange on-premises, self-hosted servers (Dovecot, Zimbra) and any ordinary hoster.
Authentication is OAuth2/XOAUTH2 by default, with three grants — client_credentials (app-only), authorization_code (one-time consent) and jwt_bearer (service account with domain-wide delegation). Username/password over TLS remains available for servers without OAuth2. Per-mailbox secrets are stored encrypted.
Features¶
- Per-project mailboxes — source and target folders, defaults for tracker, priority and status, handling of unknown senders.
- Autoresponder — configurable confirmation mail for new tickets.
- Customer replies from the ticket page, with header/footer templates, inline images (CID), attachments and CC/BCC. Sent through the mailbox itself, so a copy lands in its Sent folder.
- Address autocomplete — To/CC/BCC suggest matching project contacts.
- Quoting and answer templates — next to the formatting icons of the note field, a Quote button inserts the original mail, the complete conversation or only the mail exchange (private notes never among them), and a Templates button inserts a stored answer with its macros already resolved. Templates are maintained globally and per project.
- Embedded images — inline images of an incoming mail are shown in the ticket where the mail showed them, instead of leaving a
[cid:…]marker behind, and images referenced in a reply are sent to the customer as inline parts. - Contacts — senders are saved automatically; customer list per project and a customer panel with previous tickets on the ticket page.
- Black-/whitelists — sender and domain filters per mailbox.
- SLA — reaction and solution targets in business minutes, per-priority overrides, traffic-light display, sortable and filterable SLA columns in the issue list, breach notification via a cron endpoint, plus an "SLA statistics" tab with charts.
- Phishing detection — optional check of incoming links against a local mirror of PhishTank and the Phishing.Database feed, Microsoft SafeLinks decoded locally. On a hit the links are neutralised or the mail is quarantined, per project.
- AI summaries and knowledge base (optional) — per-project mail summaries via OpenAI, Anthropic or an OpenAI-compatible endpoint, and a RAG knowledge base built from resolved tickets (Qdrant or pgvector). Off by default.
- Awaiting response — a ticket is flagged when a customer replies by mail or a reply reopens a closed ticket, and unflagged when an agent answers publicly or closes it. Sortable column and filter in the issue list, a marker on the row, a sidebar counter and a My page block.
- Ticket assignment — new tickets from mail go to a user or a group chosen per project, a matching rule overrides that for the mail it applies to, and the "assign to me after reply" option claims only a ticket nobody holds yet.
- Rules — automation by subject or sender: set priority, tracker, category, assignee (user or group), or ignore the mail.
- Initial mail — assign a customer contact to any ticket and optionally send the first outbound mail.
- REST API (JSON and XML) following Redmine's own conventions, authenticated with
X-Redmine-API-Keyand scoped by the existing permissions: contacts, tickets, per-project settings and mailboxes. Mailboxes are fully configurable over the API — backend, IMAP/SMTP hosts, OAuth2 credentials, folders — with atest_connectioncall to verify one. Secrets can be written but are never returned.
Requirements¶
- Redmine 5.1.x, 6.0.x, 6.1.x or 7.0.x
- No additional gems — Ruby standard library only
The pgvector knowledge-base backend is the one exception and needs gem 'pg' in your deployment; the default Qdrant backend does not.
Links¶
License¶
GNU General Public License, version 2 or later — the same license Redmine itself uses.
Installation notes
Requirements¶
- Redmine 5.1.x, 6.0.x, 6.1.x or 7.0.x
- No additional gems — Ruby standard library only
Every release is tested against Redmine 5.1, 6.0, 6.1 and 7.0 on a clean MariaDB, and additionally booted inside the official redmine Docker images for the same versions.
The only exception to "no gems" is the optional pgvector backend of the knowledge base, which needs gem 'pg' in your deployment. The default Qdrant backend does not, and both are off unless you enable them.
1. Install the plugin¶
Download redmine_expert_helpdesk-<version>.zip (or .tar.gz) from the Releases page. The archive already contains a top-level redmine_expert_helpdesk/ folder, so extract it directly into your Redmine plugins/ directory:
cd /path/to/redmine/plugins unzip redmine_expert_helpdesk-<version>.zip
Alternatively, from source:
cd /path/to/redmine/plugins git clone https://github.com/expertZentrale/redmine_expert_helpdesk.git
The directory must be named redmine_expert_helpdesk — Redmine derives the plugin id from it, and the plugin's own asset and settings paths depend on it.
2. Run the migrations¶
cd /path/to/redmine bundle exec rake redmine:plugins:migrate NAME=redmine_expert_helpdesk RAILS_ENV=production
Then restart Redmine so the plugin is loaded — touch tmp/restart.txt for Passenger, or restart the Puma/Unicorn service.
3. Enable the module and grant permissions¶
Enable expert Helpdesk per project under Project settings → Modules, then assign the permissions under Administration → Roles and permissions:
| Permission | Grants |
|---|---|
| Manage helpdesk mailboxes | Mailbox configuration, folders, rules |
| Fetch helpdesk mails | The "Fetch mails now" button |
| Send customer replies | Reply form, contact autocomplete, initial mail |
| View helpdesk info | Info bar and sidebar on the ticket page |
| Manage contacts | Customer list and customer profile |
| View SLA statistics | The project's "SLA statistics" tab |
View AI statistics is the one global permission — it is granted once to a role and then applies across all projects without project membership, because it exposes the token spend of the AI features. The tab it unlocks is shown only where the AI features or the knowledge base are enabled; with both switched off it stays hidden and the page answers 403.
4. Central configuration¶
Under Administration → Plugins → Redmine expert Helpdesk, or via the expert Helpdesk entry in the Administration menu, which links there directly.
| Setting | Purpose |
|---|---|
| Tenant ID / Client ID / Client Secret | The Azure app registration, used by Microsoft 365 mailboxes and shared by IMAP/SMTP mailboxes that authenticate with OAuth2 |
| Default credentials for IMAP/SMTP | Preset, grant, authorization and token URL, scope, plus default IMAP/SMTP host, port and encryption |
| API key (mail fetch) | Secures the global helpdesk/fetch_all endpoint |
| API key (SLA check) | Secures the helpdesk/sla_check endpoint |
| Entries per page | Page size of the customer list (default 25) |
| Max. tickets in customer profile | Tickets shown in the customer detail view (default 10) |
| Mark tickets awaiting a response | Flags tickets whose customer replied by mail and clears the flag when an agent answers (on by default) |
| Answer templates | Global canned responses offered in every helpdesk project, in addition to a project's own ones |
| Embedded images | Rewrites the [cid:…] markers of incoming mails to the stored image attachment (on by default) |
Nothing here is required for a mailbox that carries its own credentials — see the next step.
5. Add a mailbox¶
Under Project settings → Helpdesk, add a mailbox and pick its Mail provider:
| Provider | Incoming | Outgoing | Typical use |
|---|---|---|---|
| Microsoft 365 (Graph) | Graph API | Graph sendMail |
Microsoft 365 / Exchange Online |
| IMAP / SMTP | IMAP | SMTP | Google Workspace, Exchange on-premises, Dovecot, Zimbra, any hoster |
Credentials is an explicit switch, not a fallback chain. From plugin settings uses the central app registration above; Individual for this mailbox uses only the mailbox's own fields. A mailbox uses one source entirely — blank fields are deliberately not filled in from the other, so a half-configured mailbox cannot silently authenticate against the wrong tenant.
Use Test connection before saving. It performs a real login, lists the folders and probes the outgoing route, so a wrong port, encryption mode or credential surfaces immediately instead of on the first fetch.
For Microsoft 365 the app registration needs the application permissions Mail.ReadWrite and Mail.Send, granted with admin consent.
6. Schedule the fetch¶
There is no built-in scheduler. Mail is fetched either with the Fetch mails now button in the project settings, or through an endpoint meant for cron:
curl "https://redmine.example.com/helpdesk/fetch_all?key=FETCH-API-KEY"
That processes every active mailbox across all projects and piggybacks the phishing-feed sync. The SLA breach check is deliberately separate, so it can run on its own schedule:
curl "https://redmine.example.com/helpdesk/sla_check?key=SLA-API-KEY"
Both keys come from the central configuration. Endpoints without a key configured refuse the request rather than running unauthenticated.
REST API¶
The plugin's own REST API (contacts, tickets, project settings, mailboxes) is separate from the two cron endpoints above and uses Redmine's normal API authentication. Enable Administration → Settings → API → Enable REST web service; requests then authenticate with an X-Redmine-API-Key header and are authorized by the same permissions as the UI. Mailbox endpoints require manage_helpdesk for reading as well as writing, because the configuration exposes mail hosts, usernames and OAuth client ids. Full reference: API.md
Upgrading¶
Replace the plugin directory with the new version, then run the migration command from step 2 again and restart. Migrations are additive and existing mailboxes keep their configuration; if a release needs anything beyond that it is called out in that version's notes.
Downgrading is not supported — roll back the database alongside the plugin if you need to.
Uninstalling¶
bundle exec rake redmine:plugins:migrate NAME=redmine_expert_helpdesk VERSION=0 RAILS_ENV=production rm -rf plugins/redmine_expert_helpdesk
This drops the plugin's tables and all helpdesk data — contacts, message log, SLA tracking. Tickets created from mail are ordinary Redmine issues and stay.
Changelog
0.4.0 (2026-08-13)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Added¶
- New tickets can be assigned to a fixed user or group, per project. Until now the plugin could only put a ticket on the agent who happened to answer it: a ticket arriving by mail was created unassigned, and the only way to route it anywhere was a mailbox rule matching subject or sender. Teams working out of a shared queue — 2nd level, an on-call group, a dispatcher — could not express that at all, because nothing in the plugin could address a group. Project settings → expert Helpdesk → Reply settings now carries Assign new tickets to, a dropdown of the project's assignable principals split into Users and Groups, preset to "none" so nothing changes for existing projects. It applies when incoming mail creates a ticket, and only then — replies never re-assign, so an agent's manual decision always stands.
- Mailbox rules can assign to a group. The rule action Assign to resolved its value against the project's members and could therefore only ever find a user, which left the rules engine unable to express the same routing the new project default supports. The dropdown is built from the project's assignable principals, groups marked as such, and stores the principal id. Rules created before this release store a login and keep resolving unchanged.
Changed¶
- "Assign ticket to me after reply" only takes effect while the ticket is still unassigned. The option overwrote the assignee on every single reply, so a ticket a dispatcher had just routed to 2nd level was silently taken over by the first agent who answered — and an assignee picked in the very same form was discarded on send. It now claims the ticket only when nobody holds it, which is what the option was meant to do; existing assignments, to a user or a group, are left alone.
- Rules assigning a ticket now use the project's assignable members rather than all members. A member whose role is not assignable could previously be set as assignee by a rule, which the ticket form itself would refuse.
Upgrade notes¶
This release runs a migration. One column is added to the per-project settings:
bundle exec rake redmine:plugins:migrate NAME=redmine_expert_helpdesk RAILS_ENV=production
No new permission is introduced, and no existing project changes behaviour on upgrade: Assign new tickets to starts empty, which means "do not assign" — exactly what happened before.
The reply option behaves differently after the upgrade. If you relied on Assign ticket to me after reply to move a ticket to whoever answered last, it no longer does that once somebody is assigned. Clear the assignee to hand a ticket back to the pool, or set a project default so tickets start on a group and agents claim them from there.
Three settings now decide who owns a new ticket, in this order: an Assigned to: keyword in the mail, which Redmine's own MailHandler has already honoured before the plugin looks; a matching mailbox rule; and the project default. The option list comes from the same source as the ticket form, so Groups appear only while Allow issue assignment to groups is enabled under Administration → Settings → Issue tracking. A user or group that later loses its role or leaves the project is silently skipped instead of producing invalid tickets — the setting is not cleared, so restoring the membership restores the routing.
0.3.0 (2026-08-06)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Added¶
- Prior ticket content can be quoted into the reply with one click. Agents answering a customer were copy-pasting out of the ticket history by hand, which loses the
>prefixing mail clients need to fold a quote — and silently drags along whatever happened to be selected. A Quote button now sits next to the formatting icons of the note editor with three entries: Original email quotes the ticket description (the mail that became the ticket, embedded images already resolved), Complete conversation adds every public journal note, and Email conversation adds only the notes belonging to a mail actually exchanged with the customer. Entries carry author and timestamp and are separated by a horizontal rule, so a long history stays readable while scrolling. Private notes are excluded from all three — including for agents who are allowed to read them, because the text is destined for a customer.
- Answer templates, globally and per project. Support cases repeat, and until now every acknowledgement, follow-up question and closing text was retyped. A Templates button next to the Quote button inserts a stored answer. Global templates are maintained under Administration → Plugins → Redmine expert Helpdesk, project templates in the project settings tab expert Helpdesk; a project's own templates are offered first, so it can override a central wording by reusing its name. Templates understand the same macros as autoresponder, header/footer and subject templates, and the macros are expanded at insertion time against the ticket, its customer and the acting agent.
- Embedded images of an incoming mail are shown in the ticket instead of the
[cid:…]marker the mail client left behind, so a signature arrives as a logo rather than as[cid:image001.png@01DD2980.37ED1560]. Outlook's[cid:…], Gmail's[image: …]and<img src="cid:…">are all recognised and rewritten to the image syntax of the configured formatting, pointing at the attachment that was just stored. The archived.emlkeeps the untouched original, and markers without a matching attachment are left alone.
- Outgoing mails carry their send time in the journal header, the same way received mails already did, so the correspondence can be followed on one time axis instead of reading the outgoing side off the journal's own timestamp — which is when the note was saved, not when the mail left.
- The mailbox connection test can copy the whole message. Provider errors are long and the status line wraps; Copy message puts the full text on the clipboard, and where the clipboard API is unavailable — an internal Redmine over plain http is not a secure context — it selects the text instead of failing silently.
Fixed¶
- Images already attached to the ticket never reached the customer. Only images an agent had just pasted or dropped into the form were sent as inline mail parts; anything already stored on the ticket stayed a relative reference that means nothing in a mail client, so the customer received an empty box. This was invisible while pasting was the only way to get an image into a reply, and became obvious once quoting made it easy to reference the pictures of the original mail.
-WhatIfdid not stop the Entra ID writes insetup-azure-app.ps1. It was documented as a dry run and guarded the Exchange Online calls, but the Microsoft Graph ones ran regardless.
Changed¶
setup-azure-app.ps1can add mailboxes to an existing setup instead of aborting as soon as an app registration with the given name exists. Onboarding one more project no longer means tearing the tenant setup down and rebuilding it — which would mint a new client secret and force a Redmine config change.
-ListRoleAssignmentsshows which mailboxes a scope actually covers, by asking Exchange Online to evaluate the filter rather than reading it by eye — the only way to answer that for aCustomAttribute, domain or group filter.
Upgrade notes¶
This release runs a migration. One table is added for the answer templates:
bundle exec rake redmine:plugins:migrate NAME=redmine_expert_helpdesk RAILS_ENV=production
No new permission is introduced. Quoting and inserting a template require the existing Send customer replies permission, the same one that governs the reply form; maintaining a project's templates requires Manage helpdesk mailboxes, and the global templates are administrators only.
Quoting deliberately never includes private notes, not even for agents holding View private notes — the result is meant for a customer. For the same reason the plugin's own bookkeeping notes (autoresponder sent, phishing links removed) stay out of the quoted conversation. Very long histories are capped so the note field stays usable, and the toolbar says so rather than truncating silently.
Embedded images can be switched off under Administration → Plugins → Redmine expert Helpdesk → Embedded images if the previous behaviour is preferred.
0.2.4 (2026-08-06)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Fixed¶
- The "AI statistics" tab no longer appears when the AI features are switched off. It showed up in every helpdesk project for anyone holding the global View AI statistics permission, even with both the AI features and the knowledge base disabled — where it led to a permanently empty page. The tab now appears once at least one of the two is enabled, because the page reports both AI summaries and knowledge-base requests, and either one alone makes it meaningful. The page itself answers 403 while both are off, so it can no longer be reached by typing the URL.
- Every checkbox in the plugin settings and the mailbox form shipped a duplicate DOM id. Each checkbox is preceded by a hidden field carrying its unchecked value, and both were given the same id, derived from the shared field name — so
getElementByIdreturned the invisible hidden field instead of the checkbox. Twelve checkboxes were affected. Saving the forms was never affected, which is why it went unnoticed.
Upgrade notes¶
No migration, no new setting, no new permission.
One visible change on upgrade: sites that hold the View AI statistics permission but run with the AI features and the knowledge base switched off will find the tab gone. Enabling either one under Administration → Plugins → Redmine expert Helpdesk brings it back with all of its history intact — nothing is deleted, only hidden.
0.2.3 (2026-08-06)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Added¶
- Tickets waiting for a response are now visible at a glance. When a customer replied by mail to an existing ticket — or a reply reopened a closed one — nothing marked that ticket as needing attention, and agents had to fall back on filtering by SLA status. A ticket is now flagged Awaiting response as soon as an inbound reply arrives on an existing ticket, and the flag clears the moment an agent posts a public note or closes the ticket. Four places show it: a sortable Awaiting response column and filter in the issue list, a marker on the row itself, a counter in the issue-list sidebar, and a "Helpdesk: awaiting response" block for My page. The stored timestamp is that of the oldest unanswered reply, so a second mail does not make a ticket that has been waiting for days look fresh. A private note deliberately does not clear the flag — an internal remark is not an answer to the customer.
- Short mails no longer cost an AI call. A two-line "please call me back" summarises to itself, yet every ingested mail was sent to the provider. The new Min. input length setting skips the call below a configurable number of characters.
- AI diagnostics have their own log level. The diagnostic lines about input length and skip decisions can be raised, lowered or silenced independently of the rest of the log. AI errors are always logged.
- Every outgoing mail is logged with the transport it took. Replies, initial mails, autoresponder mails and SLA notifications leave over three different transports and previously all looked alike in the log. Each send now records which one it used; failures are always logged as errors.
Fixed¶
- Auto-reopening a ticket now shows up in its history. The reopen status was written without a journal entry, so a ticket jumped from closed back to open with no trace in the ticket history or the activity feed — nothing indicated why it had reopened. The status change is now recorded on the journal that the inbound reply already creates: one history entry rather than two, and no extra notification mail.
- Graph was offered as the send path for IMAP mailboxes it cannot serve. The rule read the mailbox's
oauth_presetcolumn, which is not in force for a mailbox using the central credentials, so the option appeared where it could not work.
Changed¶
- The send path moved next to the mail provider in the mailbox form, where it belongs — it governs replies, initial mails and the autoresponder alike, not just replies.
Upgrade notes¶
This release runs a migration. Two columns are added to helpdesk_ticket_infos for the awaiting-response flag:
bundle exec rake redmine:plugins:migrate NAME=redmine_expert_helpdesk RAILS_ENV=production
Existing tickets start unflagged; the flag is set from the next inbound reply onwards.
The feature is on by default and can be switched off under Administration → Plugins → Redmine expert Helpdesk. Switching it off hides the column content, row markers, sidebar counter and My page block. No new permission is needed — the existing expert Helpdesk project module and the Send customer replies permission govern it, the latter deciding whose public note counts as an answer.
0.2.2 (2026-08-04)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Added¶
- Mailboxes can now be managed over the REST API. The generic IMAP/SMTP support in 0.2.0 gave a mailbox a large configuration surface — which backend it uses, IMAP and SMTP hosts, OAuth2 credentials, folders — but none of it could be reached from outside the web interface, and a ticket fetched over the API did not even say which backend its mail had arrived through.
There is now a full set of endpoints: list and create mailboxes per project, read, update and delete an individual one, and a test_connection call that probes the stored settings and reports the folders it can see. Reading requires the same manage_helpdesk permission as writing, because a mailbox exposes mail hosts, usernames and OAuth client ids.
Secrets go in but never come back out: the mailbox password, OAuth client secret and service-account key can be set through the API and are never returned. Responses only report whether one is stored. Sending a single hyphen clears a stored secret, matching the masked fields in the web interface. The interactive OAuth consent stays in the browser, where an identity provider needs it.
- AI summary and knowledge-base settings are available over the API. The per-project settings endpoint quietly left out every AI and knowledge-base field, so those two features could only be configured by hand. They are now read and written like the SLA and phishing settings.
Fixed¶
- Phishing detection stopped working on Ruby 4.0. Microsoft SafeLinks and other redirect links are unwrapped by reading the original address out of the link's query string. The method used for that was removed in Ruby 4.0, so on Redmine 7 every link carrying a query string raised an error: SafeLinks were no longer decoded and redirect links were never flagged. Query strings are now parsed with a method that is not going away.
- Documentation no longer describes the plugin as Microsoft-365-only. The README still opened by calling this a Microsoft 365 plugin, months after generic IMAP/SMTP had shipped, and the plugin description shown in Redmine's own plugin list said the same. Both now state the actual choice of backends. The READMEs also gained a table of contents, and the German edition was brought back in line with the English one — it was missing a section entirely.
Upgrade notes¶
No migrations and no configuration changes. Existing mailboxes are untouched.
To use the new endpoints, enable the REST web service under Administration → Settings → API; requests authenticate with the usual X-Redmine-API-Key header and are authorized by the existing helpdesk permissions.
0.2.1 (2026-08-04)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Fixed¶
- The folder fields on the mailbox form are real dropdowns now. All five (source, processed, skipped, failed, sent) were text inputs backed by an HTML
datalist, which browsers draw exactly like their own autofill history — so a folder genuinely read from the mailbox was indistinguishable from a value typed into the field once before.
Each field now has a chevron that opens the full folder list and filters by substring while typing, so arbeit finds Verarbeitet. Arrow keys, Enter, Escape, hover and mouse selection all work. Free text stays valid: a folder that does not exist yet is offered for creation and is still created when the form is saved.
The field and the list follow the active Redmine theme — the input uses the same chevron and metrics as a native select, and the list reuses Redmine's own autocomplete styling. No new dependency.
0.2.0 (2026-08-03)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Added¶
- Generic IMAP/SMTP mailboxes. Until now mail could only be fetched from Microsoft 365 via the Graph API. A mailbox now picks its backend itself, so Google Workspace, Exchange on-premises, self-hosted servers (Dovecot, Zimbra) and ordinary hosters work as well. Incoming mail arrives over IMAP, outgoing mail leaves through the mailbox's own SMTP server.
- OAuth2 (XOAUTH2) as the default authentication, with three grants:
client_credentials(application-only),authorization_code(one-time consent through the browser) andjwt_bearer(service account with domain-wide delegation, assertion signed locally). Username/password over TLS stays available for servers without OAuth2. - Per-mailbox secrets are stored encrypted — client secrets, refresh tokens, passwords and service-account keys. Existing plaintext values keep working, so no data migration is forced.
- Connection presets for Microsoft, Google and generic servers prefill host, port and encryption, and central defaults can be set once under Administration for operators running a single mail server.
- "Test connection" button on the mailbox form: verifies login, lists the folders and probes the outgoing route in one step.
Fixed¶
- Rotating an OAuth2 client secret did not invalidate the cached access token — the token issued for the superseded secret stayed in use until it expired.
- A new IMAP mailbox defaulted to a reply transport its own validation rejects.
- Connection presets and the central defaults could never set a port or an encryption mode; only the host fields worked.
- An IMAP mailbox could be configured to send through Microsoft Graph even when Microsoft does not host it.
- The autoresponder ignored the mailbox's reply transport and always sent through Graph.
- Boot failure and a silently missing OAuth controller when installed alongside RedmineUP's helpdesk plugin.
Upgrade notes¶
Migrations 034–037 run on upgrade. Existing Microsoft 365 mailboxes are untouched and keep using the Graph API — the new backend is opt-in per mailbox.
0.1.6 (2026-08-03)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.
Documentation: "Flow per mailbox fetch" brought back in sync with `MailProcessor`.
The diagram had drifted and was missing the auto-reply filter, the phishing scan (quarantine vs. neutralize), the MIME preprocessing stage (thread-header stripping for the reopen-age limit, `Auto-Submitted` stripping on NDRs, `In-Reply-To`/`References` injection), ticket reopening on replies, the `HelpdeskTicketInfo` link and the async AI-summary enqueue.
It also showed a single "target folder" where the code actually uses three (`processed_folder` / `skipped_folder` / `failed_folder`, with fallbacks).
Adds notes on target folders and per-message failure isolation. Mirrored in `README.de.md`.
`LICENSE` file (GPL-2.0-or-later)
The plugin is now explicitly licensed under the GNU General Public License v2 or later, matching Redmine itself.
Adds a copyright/license header to `init.rb` and a License plus Third-party components section to `README.md` / `README.de.md`, documenting the bundled MIT-licensed Chart.js 4.4.6 and chartjs-plugin-datalabels 2.2.0, both served locally — no CDN request at runtime.
Screenshots in both READMEs
`README.md` and `README.de.md` now open with a short gallery of the main screens (SLA statistics, AI statistics, customer list, ticket view) and carry inline screenshots in the customer, AI-summary and knowledge-base sections, so the plugin can be evaluated without installing it first.
Images live in `docs/screenshots/{en,de}/` and are excluded from the release archives (`--exclude='docs'` in `.github/workflows/release.yml`), so the installable package does not grow.
New maintenance scripts
`scripts/seed_screenshot_demo.rb` and `scripts/teardown_screenshot_demo.rb` build and remove the synthetic demo project the screenshots are taken from (contacts, tickets with a realistic SLA mix, AI request log, knowledge-base entries).
Both are scoped to a single project, write no global settings and are excluded from the release archives along with the rest of `scripts/`.
0.1.5 (2026-07-29)
Compatible with Redmine 7.0.x, 6.1.x, 6.0.x, 5.1.x.