Skip to content

Mailbox connection

invoiceR collects invoices from a mailbox using IMAP. This page describes the technical connection of the mailbox. For an overview of sending and import see Sending and importing email.

  1. A recurring job checks the mailbox at a fixed interval (typically every few minutes).
  2. Every new email in the inbox folder is registered and moved to the Received folder.
  3. If the email contains exactly one PDF (or none), invoiceR creates an import entry and starts the document import. The email moves to Imported.
  4. If it contains several PDFs, it moves to ManualProcessing. If the import fails, it moves to Aborted.

Create these folders as subfolders of the inbox before you start the import.

MethodWhen to use
Client credential flow (OAuth, app with client secret)Recommended for Microsoft 365. No user password needed.
Password flow (OAuth with user name and password)Only if the client credential flow is not possible. The mailbox account must not require multi-factor sign-in.
Basic authentication (user name and password directly on the IMAP server)For your own IMAP servers outside Microsoft 365.
  1. Create an app registration and note the Tenant ID, the Application (client) ID and the value of the Client Secret.
  2. Under API permissions > Add a permission > APIs my organization uses, add the API Office 365 Exchange Online and select the application permission IMAP.AccessAsApp.
  3. Grant admin consent with Grant admin consent.
  4. Open the same app under Enterprise applications and note the Object ID shown there. This is the object ID of the service principal, not the one of the app registration.

To let the app access the mailbox, register it in Exchange Online and grant access. Open PowerShell as administrator:

Terminal window
Install-Module -Name ExchangeOnlineManagement
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@contoso.ch
# Register the service principal in Exchange
New-ServicePrincipal -AppId <application-id> -ServiceId <enterprise-app-object-id>
# For each mailbox to import from
Add-MailboxPermission -Identity "invoices@contoso.ch" -User <enterprise-app-object-id> -AccessRights FullAccess

If the app also has the Mail.Send permission (for sending through Microsoft Graph), it could send on behalf of any mailbox. To restrict this:

  1. In the Exchange admin center, create a mail-enabled security group containing only the mailboxes invoiceR may send from.
  2. Create the policy and test it:
Terminal window
New-ApplicationAccessPolicy -AppId <application-id> -PolicyScopeGroupId invoicer-sending@contoso.ch `
-AccessRight RestrictAccess -Description "invoiceR may only send from this group"
Test-ApplicationAccessPolicy -Identity invoices@contoso.ch -AppId <application-id>
  1. Create an app registration and note the Tenant ID and the Application (client) ID. You do not need a client secret.
  2. Under Authentication, turn on Allow public client flows.
  3. Under API permissions, add delegated permissions for Microsoft Graph (email, offline_access, IMAP.AccessAsUser.All, User.Read) and grant admin consent.
  4. Make sure the mailbox account does not require multi-factor sign-in.

invoiceR then signs in with the mailbox user name and password and obtains an OAuth token.

The import settings are stored as JSON in the table conf.IrManagers, in the entry with the ClassIdentifier invoiceR.PreSort.PreSortManager (column Configuration). enio usually sets up this entry. Example for Microsoft 365 with client credential flow:

{
"TempFolder": "D:\\invoiceR\\MailImport",
"SaveAttachments": false,
"Mail": {
"Imap": {
"HostName": "outlook.office365.com",
"Port": 993,
"UseSsl": true,
"UserName": "invoices@contoso.ch",
"UseOAuth": true,
"OAuthTenantId": "<tenant-id>",
"OAuthClientId": "<application-id>",
"OAuthClientSecret": "<client-secret>"
}
},
"CommonMail": {
"InboxFolder": "INBOX"
},
"DefaultImportValues": {
"MandatorCode": "100",
"ProcessType": "GK",
"InvoiceType": "R"
}
}
KeyMeaning
HostName, PortIMAP server and port; for Microsoft 365 outlook.office365.com and 993.
UseSslUse an encrypted connection.
UseStartTlsUpgrade an unencrypted connection to TLS with STARTTLS.
IgnoreCertificateIgnore certificate errors (for example self-signed certificates). Use only as a last resort.
UserNameMailbox address.
PasswordPassword, only for password flow and basic authentication.
IsSharedMailboxtrue for a shared mailbox with basic authentication; the user name is then admin@contoso.ch\mailbox.
UseOAuthtrue for Microsoft 365.
OAuthTenantId, OAuthClientIdTenant ID and application ID of the app registration.
OAuthClientSecretSet: client credential flow. Empty: password flow.
KeyDefaultContent
InboxFolderINBOXFolder checked for new emails.
ReceivedFolderINBOX/ReceivedEmails that are registered and being processed.
ImportedFolderINBOX/ImportedSuccessfully imported emails.
ManualProcessingFolderINBOX/ManualProcessingEmails with several PDFs that someone must process by hand.
AbortedFolderINBOX/AbortedEmails whose import failed.
KeyMeaning
TempFolderFolder on the server where the PDFs are stored for import.
SaveAttachmentstrue also saves the other attachments next to the PDF.
DefaultImportValuesDefaults for the new document: MandatorCode, ProcessType, InvoiceType, CostCentreCode, SupplierCode, DeleteImportFile.
MetadataAttachmentContainsFilterIf an attachment’s file name contains this text (default meta), invoiceR reads it as JSON with additional data.
PropertyMappingsMaps values from this JSON file to import fields (IrCaseImportPropertyName, JsonSelectTokenPath, DataType).

The collection is started by the job Run Email Check in conf.IrRecurringJobs with ClassIdentifier enio.tool.Plugin.CheckMailbox.RunEmailCheck, MethodName DoCheck and MethodArgumentIdentifier enio.tool.Plugin.CheckMailbox.RunEmailCheckArgument. How to create jobs is described in Recurring jobs.

E-invoices through Conextrade (Swisscom) do not arrive through a mailbox but through a separate import job that collects the invoices via SFTP (InvoiceR Conextrade Import). enio sets up this job together with the access data from Conextrade.

  • You can see the history of each run in the Hangfire dashboard (Administration > Hangfire dashboard) for the job Run Email Check.
  • If emails end up in Aborted, the reason is in the job log. Often the access to TempFolder is missing or a required value in DefaultImportValues.
  • If sign-in fails, first check whether the client secret has expired.