grommunio Knowledge Base

grommunio GmbH

2026-07-02

Knowledge Base

This section is a collection of unstructed notes.

Offline reading

This section is also available to download for offline use:

Download as PDF

Download as EPUB

Antispam

Reset the password

If you have forgotten the initial password or just want to set a new password you can do that with the following commands:

PASSWORD="YourNewPassword"NEWPASS=$(printf 'password = "%s";\n' $(rspamadm pw -p "${PASSWORD}"))sed -i -n -e '/^password/!p;$a \'"$NEWPASS" /etc/grommunio-antispam/local.d/worker-controller.inc

Archive

Login not possible

Because grommunio-archive makes use of the IMAP service (as login backend and for means of recovery from archive), you have to keep in mind that every user who is allowed to login to the archive also needs the permission to use IMAP/POP which needs to be enabled in the API, see Account </admin/administration.html#account>_.

Understanding MAPI and Aliases

By default, grommunio such as Microsoft Exchange (on-premises and Exchange Online) does not allow users to send messages from any of their secondary (alias) email addresses. Instead, Exchange typically requires that email be sent from either the primary SMTP address of a mailbox or from another mailbox/address for which the user has explicit "Send As" or "Send on Behalf of" permissions. Here are the key reasons why "sending as an alias" can be problematic and how Microsoft has approached this limitation:

Behavior in grommunio (and Exchange)

- Single Primary SMTP Address: In traditional Exchange environments (and by default in Exchange Online), each user mailbox has one "primary" SMTP address. That address is the one used when you send an email.

- Alias Addresses: Mailboxes can have multiple "proxy" or "alias" addresses, but these aliases exist primarily for receiving email. By default, Exchange does not allow you to send out through an alias.

From Microsoft’s standpoint, alias addresses are designed to ensure that a mailbox can receive email sent to multiple addresses or domains. Security and administrative considerations also come into play: Exchange wants to be explicit about which identity a user is sending from. Also, there are many other technical reasons, one of them is that MRs (meeting requests) also have the attendees identifiable through SMTP addresses. Using different aliases with meeting requests would therefore be prone to errors in matching these objects beyond the now-point-in-time view (for example switching aliases at different times).

Alternative workarounds

If you are using an on-premises deployment of Exchange (2016, 2019, etc.), out-of-the-box "Send from Alias" is also not currently supported, just like with grommunio.

Possible workarounds include:

Shared/Resource Mailbox: Create a separate mailbox or shared mailbox that has the desired alias as its primary address, then grant "Send As" permissions to your user. You can then select that mailbox as the From address.

Third-Party Tools or Transport Rules: Some organizations use custom transport rules or third-party utilities that rewrite the From header to appear as an alias. This is more complex, can be tricky to maintain, and may introduce mail-flow side effects.

With grommunio, we traditionally use Postfix as our main MTA (which is built-in with every appliance) and the recommended MTA. It is possible to create transport rules on that basis, like you can see based on the following example with a fixed recipient.

Alias transport rule in Postfix

Caution

Please note to validate your transport maps appropriately, as they directly manipulate your MTA configuration. Take care and validate both rewriting and non-rewriting mail routing to work as expected.

In /etc/postfix/main.cf you can enable header checks with:

header_checks = pcre:/etc/postfix/header_checks

and use the appropriate header_checks file with (example):

/^(From:.*myuser@mydomain\.at)(\r?\n(.*\r?\n)*?^To:.*special@destination\.com)/m    REPLACE From: alias@mydomain.at

After that, do not forget to create the appropriate postfix map:

postmap /etc/postfix/header_checks

How it works: When Postfix processes the headers of an outgoing email, it checks for a From line matching myuser@mydomain.at. It then looks ahead in the next lines for a To line matching special@destination.com. If both conditions are met in that single message header, it rewrites the From header to alias@mydomain.at. If the message is going to any other recipient, no rewriting occurs.

Of course, this is just an example, there are many possibilities to extend this by for example replacing the sender or the recipient(s) in a more generalized way.

Summary

By default, grommunio acts the same way like Microsoft Exchange in this case. Main Reason for that is the MAPI core technology which is the foundation of both.

Historically, aliases were for receiving mail only, and Microsoft locked down sending behavior for clarity, security, and auditability. However, the newer Microsoft 365 Exchange Online feature "Send from Alias" can be enabled by an admin to address this limitation in the cloud. This is done by rewriting addresses in the mail transport queue in M366. For on-premises Exchange, administrators generally need to rely on workarounds (such as shared mailboxes or distribution groups with "Send As" privileges). With grommunio you can use our provided Postfix to define generalized alias transports or use the same methods as common with Microsoft Exchange (and many other solutions).

AutoDiscover

As of 2024-11-16, the content of this page was moved into the Gromox manpage autodiscover(7) and our KB page on Outlook.

M365 authentication dialog

When a DNS zone is M365-enabled (DNS TXT record on the domain with contents like MS=ms12345678), Outlook will present a mini browser window for M365 authentication. This can be permanently disabled by setting ExcludeExplicitO365Endpoint:

[HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Outlook\AutoDiscover]"EnableOffice365ConfigService"=dword:00000000"ExcludeExplicitO365Endpoint"=dword:00000001
[HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\16.0\Outlook\AutoDiscover]"EnableOffice365ConfigService"=dword:00000000"ExcludeExplicitO365Endpoint"=dword:00000001

EnableOffice365ConfigService

In Outlook versions before 16.0.9327.1000, this URL was used to automatically provision O365 endpoints, overriding some AutoDiscover behavior

ExcludeExplicitO365Endpoint

In Outlook 2016+ (versions after 16.0.6741.2017), this configuration parameter is used to proxy AutoDiscover requests via Microsoft servers. Usage of this service is possible

# with grommunio if the AutoDiscover entries have been configured, and/or # when globally resolvable records are pointing to grommunio as the endpoint.

For configuration via Group Policy, ADMX templates can be found at https://www.microsoft.com/en-us/download/details.aspx?id=49030.

Connection Analyzer

Silly check for fixed RSA cipher types

When the server certificate's private key is of RSA type, all is fine:

$ openssl s_client -no_tls1_3 -connect mail.grommunio.com:443 0 s:CN = mail.grommunio.com   i:C = US, O = Let's Encrypt, CN = R3   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256   v:NotBefore: Aug 27 21:02:07 2024 GMT; NotAfter: Nov 25 21:02:06 2024 GMT    ...    Protocol  : TLSv1.2    Cipher    : ECDHE-RSA-AES256-GCM-SHA384

Let's Encrypt (certbot) produces ECDSA signatures, which means the ciphers will be ECDHE-ECDSA instead, and Connection Analyzer behaves completely stupid.

$ openssl s_client -no_tls1_3 -connect a4.inai.de:443 0 s:CN = a4.inai.de   i:C = US, O = Let's Encrypt, CN = R3   a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256   v:NotBefore: Sep 23 22:10:43 2024 GMT; NotAfter: Dec 22 22:10:42 2024 GMT    ...    Protocol  : TLSv1.2    Cipher    : ECDHE-ECDSA-AES256-GCM-SHA384

Disclaimer

You might be required (by law) to add a readily visible disclaimers or imprint notices on webpages emitted by your web server.

The grommunio-web login page can be extended to show some custom text in the page bottom by populating the /etc/grommunio-web/disclaimer.html file with the desired contents.

Note

This currently does not work with grommunio-keycloak, as keycloak has its own login page.

Debugging message content

Determining internal message id

Issue: You need to figure out the internal ID of a folder/message object that already exists in a Gromox store.

Actions: In MFCMAPI, navigate to the particular profile / store / folder / message, and open the PR_ENTRYID property in detail by using mouse-doubleclick or the ENTER key. In the lower-right grey-backed panel, the ID is shown in hexadecimal next to the Folder Global Counter/_Message Global Counter label (highlighted in the screenshot). Make sure that the profile is in Online Mode to get a usable value.

In grommunio-web, right click the message and call up the Options dialog. There will be a field for Object ID. (g-web does not offer this for e.g. Calendar/Contact items yet; the Options dialog for those mail items is still missing the field.)

Extracting objects

Issue: You wish to extract a MAPI message object for further diagnosis.

Action: Using the message ID as obtained earlier, the exporter utility can be invoked with the exm2eml command. exm2eml offers various output formats, depending on user/developer needs. By default, it generates RFC5322 Internet Mail format. The conversion from MAPI to RFC5322 Internet Mail format and back is not necessarily idempotent/lossless, so the use of the Gromox Message Transfer stream format (GXMT) (with --mt) or TNEF (--tnef) may be warranted.

gromox-exm2eml --mt -u test@host.example.net 0x314cc >0x314cc.eml
gromox-exm2eml --mt -u test@host.example.net 0x314cc >0x314cc.mt

Terminal window

Moving a message to another folder assigns new a object ID.

Messages in delivery

Observation: gromox-delivery emits log messages about "Dispatch error".

# journalctl -u gromox-delivery...exmdb_client_do_rpc: Dispatch erroroxcmail_import:2870: returned falseSMTP message queue-ID: 2, FROM: doc@example.com, TO: doc@example.com  fail to convert rfc5322 into MAPI message object

Cause: The TCP connection between gromox-delivery and gromox-http (exmdb_provider subcomponent) ended unexpectedly. Routine(s) for converting Internet Mail to MAPI objects thus could not complete.

Action to take: Check the system logs for indications that gromox-http has suffered a crash, or that an administrator has willingly stopped the process.

Observation: gromox-delivery emits log messages about failed RFC5322-to-MAPI conversion such as the following (but without the above-mentioned "Dispatch error").

# journalctl -u gromox-delivery...oxcical_import:1234: returned null/false...oxcmail_import:2870: returned falseSMTP message queue-ID: 2, FROM: doc@example.com, TO: doc@example.com  fail to convert rfc5322 into MAPI message object

Cause: Suboptimal parsing routines.

Action to take: Send the message file to Grommunio Support to facilitate further investigation.

The message in question should be located in /var/lib/gromox/queue/save. Conversion failure is considered terminal and no retry will be attempted.

(There are three other errors which are not considered terminal. These are: the user database being unavailable, a permission error on disk, or a disk full event. In these cases, redelivery will be attempted and the messages placed in /var/lib/gromox/queue/cache instead. Redelivery may disappear in a future version of Gromox, because Postfix is already capable of handling this.)

The message can be found by matching up the timestamp in the log with the timestamp of the file object or, in fact, the timestamp in the filename itself. The filename usually consists of a Unix timestamp, a boot-time monotonically-increasing counter (QID), and the hostname. This file may contain small binary tags, so if looking for the exact file by way of the grep command and it complains about Binary file matches, you may need the --text option. To convert from and to Unix timestamps, the following command examples should help.

perl -e 'print scalar localtime 1699956475'
date -d "2023-11-14 11:07:55" +%s

Delivered messages & IMAP messages

Observation: A message appears incomplete in any MUA after being put into the mailbox by the gromox LDA (gromox-delivery), or put into the mailbox by an IMAP client using e.g. the IMAP APPEND command.

Cause: Conversion from Internet Mail (IM) to MAPI is lossy in nature, and the conversion procedure has unanticipatedly ignored too much of the IM content.

Action to take: Send the original EML copy of the message to Grommunio Support to facilitate further investigation.

Look into the /var/lib/gromox/user/XXX/eml/ directory. The filename is generally the one used during delivery (Unix TS + QID + hostname). If the file was created later, that may be reflected in timestamps. This should help narrowing the set of files as should the use of grep. (The binary tags from the delivery stage are not present.)

The hostname portion may be .midb. If so, that file was synthesized from a MAPI object, and does not constitute the original EML form from delivery/IMAP.

Messages imported from a MAPI source

Observation: A message appears incomplete in any MUA after import from gromox-{kdb2mt,pff2mt,oxm2mt,mt2exm}.

Observation: A message has missing metadata, mangled metadata, mangled body, or has substantial differences in how it is rendered between Outlook, grommunio-web or some IMAP client to the point that it is subjectively considered "broken".

Cause: To be determined in detail. Imports via gromox-kdb2mt/pff2mt/oxm2mt are practically lossless (compared to RFC5322 conversions) because the data model is already MAPI. Some metadata and some internal IDs and references are regenerated or dropped so messages make reasonable sense when placed in the target Gromox mailbox. But not all ancient metadata is dropped so as to provide as loss-free a conversion as is feasible, but such ancient data may cause strange behavior in corner cases. (For example, unusual recipient address types.)

Action to take: Send the MT stream file to Grommunio Support to facilitate further investigation.

For gromox-kdb2mt: Capture the standard output of the gromox-kdb2mt process to a file. The --only-obj option can help produce a smaller MT file. Depending on circumstances however, access may be needed to the entire database (interactively or a mysqldump) if the MT file is not informative enough.

For gromox-pff2mt: Capture the standard output of gromox-pff2mt to a file. The --only-nid option can help produce a minimal-size MT file. Depending on circumstances however, access may be needed to the PFF/PST/OST file if the MT file is not informative enough.

For gromox-oxm2mt: Send the .msg file to the support team.

For gromox-tnef2mt: Send the .tnef file to the support team.

Messages converted from RFC5322/5545/6350 files

Observation: A message appears incomplete in any MUA after import from gromox-eml2mt, gromox-ical2mt or gromox-vcf2mt.

Cause: Conversion from Internet Mail (IM) to MAPI is lossy in nature, and the conversion procedure has unanticipatedly ignored too much of the IM content.

Action to take: Send the original EML, iCal or vCard file to Grommunio Support to facilitate further investigation.

Messages at rest

Observation: Some operation on a mailbox that involves existing messages does not work as expected. Example use cases that would fall under this:

moving messages between folders

setting categories on messages

composing or submitting messages

MAPI-to-RFC5322 conversions for outgoing mail

Cause: To be individually determined.

Action to take: Grommunio Support may require the message object (cf. "Extracting objects"), or the entire sqlite file, located at e.g. /var/lib/gromox/X/exmdb/exchange.sqlite3, for reproduction.

Messages converted to RFC5322/5545/6350 files

Observation: gromox-http or gromox-zcore emits a log message about failed MAPI-to-RFC5322 conversion such as the following.

# journalctl -u gromox-zcore...user=test@host.example.net host=::ffff:192.0.2.37  W-1281: Failed to export to RFC5322 mail while sending mid:0x5001b

Cause: Presumably the software did not anticipate a lack of certain metadata on the message.

Action to take: Follow-up with Grommunio Support to facilitate access to the sqlite3 file. (The conversion procedure ought to succeed at all times with all MAPI messages.)

Outgoing messages

Observation: A message in "Sent Items" appears acceptable, but arrives incomplete for the recipient in their Inbox.

Cause: Suboptimal export routines.

Action to take: Local investigation by administrator, follow-up with Grommunio Support.

Procedure:

Determine the internal message ID (see top of page). The screenshot example has 0x314cc. With this ID, the MAPI-to-RFC5322 conversion can be re-enacted:

gromox-exm2eml -u test@host.example.net 0x314cc

Terminal window

If this EML looks bad: Export routine is broken. Confer with section "Messages at rest".

If this EML looks good: Look for problems in the SMTP transport or on the receiving side.

Debugging messaging services

Log level

As of Gromox gromox-1.33-72-ge09fed809, all messages have a severity level associated with them, and the Gromox daemons have a log level setting. The default level is 4 (NOTICE).

Verbose debug options

The gromox-http daemon can be made to emit more messages for detailed debugging. See the respective manpages for details.

To see these debug messages, the log level also needs to be cranked to 6 (DEBUG) in various daemons, e.g. http.cfg:http_log_level.

/etc/gromox/http.cfg: http_debug=1 to dump HTTP requests/responses as they happen. Credentials may become visible, so take care!

/etc/gromox/http.cfg: msrpc_debug=1 to dump short status reports of DCE remote procedure calls.

/etc/gromox/exchange_nsp.cfg: nsp_trace=1 to dump entry/exit to NSP (addresbook) procedures and some data.

/etc/gromox/exchange_emsmdb.cfg: rop_debug=2 to dump EMSMDB ROPs issued by clients. (One DCE call may include multiple ROP commands.)

/etc/gromox/exmdb_provider.cfg: exrpc_debug=2 to dump all issued EXMDB RPCs (network only, not shmem calls made by emsmdb)

/etc/gromox/exmdb_provider.cfg: sqlite_debug=1 to dump all SQLite SQL statements as they are issued. Failing statements will be logged in any case.

(There is no knob for mysql_adaptor SQL statements. However, failing statements will be logged in any case.)

Sending SIGUSR1 to gromox-http dumps the currently active HTTP connections and EMSMDB sessions.

Similar directives exist for other daemons:

/etc/gromox/zcore.cfg: zrpc_debug=2 to dump all issued Zcore RPCs by php-fpm.

/etc/gromox/midb.cfg: midb_cmd_debug=2 to dump all MIDB commands.

/etc/gromox/midb.cfg: sqlite_debug=1 to dump all SQLite SQL statements as they are issued.

/etc/gromox/imap.cfg: imap_cmd_debug=2 to dump all IMAP commands (without responses). Credentials may become visible.

/etc/gromox/pop3.cfg: pop3_cmd_debug=2 to dump all POP3 commands (without responses). Credentials may become visible.

Mailbox maintenance

Periodic clearing of Trash folder

To automatically empty the trash folder (a.k.a. wastebasket) of all mailboxes, you can extend the cleaner service unit with the following override (systemctl edit gromox-cleaner.service):

[Service]Environment=softdelete_purgetime=30d trashbin_purgetime=7dEnvironmentFile=EnvironmentFile=-/etc/gromox/gromox.cfgExecStart=ExecStart=/usr/sbin/gromox-mbop foreach.here.mb ( purge-softdelete -t ${softdelete_purgetime} -r / ) ( purge-datafiles ) ( emptyfld -R --delempty -t ${trashbin_purgetime} DELETED )

/etc/systemd/system/gromox-cleaner.service.d/override.conf

Troubleshooting Meet, Audio/Video

System audio output (Linux)

The system may offer multiple output devices, the presence of which may be unexpected. Be aware of HDMI channels offered by the operating system even if the physical HDMI and DisplayPort jacks have nothing plugged in.

An example from the pavucontrol program (with PipeWire backend):

The default device may even shift on its own when e.g. Bluetooth output devices are turned on/off. Verify that the desired output devices are not muted and that you have a suitable device selected as the default output device. The volume meters in pavucontrol can be used to diagnose where audio output is going to.

pavucontrol does not necessarily show all the knobs, so if need be, have a look at the alsamixer command-line program as well. This needs to be invoked with a -c argument to choose a physical soundcard, e.g. alsamixer -c 0, else it may open a virtual ALSA device that is part of the modern pipewire pipeline.

System audio input (Linux)

The system may offer multiple input devices even out-of-the-box with nothing else connected. In the following sample screenshot of pavucontrol, the system is shown to have two input devices. One of those appears to be for a headset/microphone connected via the analog jack, while the other is the microphone that is located by the laptop's integrated webcam.

The fact that both input devices are labeled nearly identical is anything but ideal, but enlarging the window helps. Verify that the desired input devices are not muted and that you have a suitable device selected as the default input device. The volume meter for each device can also be used to diagnose where audio input is picked up. alsamixer can again be used as a cross-check for extra knobs.

Bluetooth devices

In the A2DP profile, Bluetooth devices are unable to provide microphone functionality. This requires use of HFP/HSP (Headset profile/Hands-free profile, not High Fidelity Playback) instead.

Depending on the capabilities and configurationof the operating system software, the mode may be automatically switched from A2DP to HFP/HSP when recording software tries to make use of microphone functionality.

Once the device is in HFP/HSP mode, it will show up under Input Devices. When the device leaves HFP/HSP mode, pavucontrol does not automatically remove the elements from the UI until a restart.

In HFP/HSP profiles, only two codecs are offered, both of which are terrible choices: mSBC (16 kHz mono) and CVSDM (8 kHz mono).

Under PipeWire/PulseAudio, it is possible to make the browser and other programs use different hardware devices for input and output. By using the webcam microphone for input, a Bluetooth device can run with the A2DP profile.

System audio (Android)

The system settings offer multiple volume sliders.

When applications only output audio/video, “Media volume” is used.

When both output and input is requested however, “In-call volume” is used.

There is at least one known case of an Android bug wherein none of the sliders have any effect when the output device is the built-in speaker.

Ensure that the application has permissions to camera and/or microphone.

Granting AV capture (Firefox)

Depending on browser settings, pages may be blocked from asking for audio/video captures. Go to the browser settings > “Privacy & Security” (left-hand-side) > “Permissions” (heading in center pane) to investigate.

The “Block new requests” checkbox is what controls whether the Ask-vs.-Block mechanic. When requests are blocked, the URL bar will not (in Firefox 116/Linux) include enough icons and/or knobs to selectively re-enable device access for a page after the fact. Users are required to go back to settings and switch from blocking to asking.

When requests are allowed, a popup is shown when a page requests device access:

It does not matter which camera/microphone device you select (if you have more than one). The dropdown seems to only exist as a reminder which devices you have. The device selection can be made later in Meet anyway.

Subsequently, site settings can be adjusted by clicking on the camera/microphone symbol in the URL bar. Importantly, there is a third setting in Firefox, called Autoplay. The autoplay setting for a site is not part of the previous permission confirmation dialog (because autoplay settings do not have an “ask” state, just “block” or “allow”). Either way, Autoplay must be allowed for Meet to function, so do click on the site settings icon(s) and make sure all three things are allowed.

Granting AV capture (Chromium)

Depending on browser settings, pages may be blocked from asking for audio/video captures. Go to the browser settings > “Privacy and security” > “Site settings” to investigate.

If all of these radio buttons are set to “Don't allow sites…”, the browser UI will not show any dialog when permissions are requested by the page, and there is a camera icon in the URL bar on the right hand side with a tiny red box and white cross to indicate that everything is blocked.

If the page does not have all of the permissions it wanted, it may elect to show a JavaScript-controlled visual element about the permission situation in the document frame.

If any of the radio buttons in the settings are set to “Sites can ask…“, the browser will show a small dialog. The device classes that will be presented for approval in that dialog is the set of devices requested by the webpage minus the set that is permanently banned through browser settings. In other words, the dialog may show any of three outcomes: Only the “Use your microphone” label, only the “Use your camera” label, or both labels.

If any permissions were granted, the icon in the URI bar switches to the most-significant permitted device class (microphone, camera, in that order). That icon can then be used to call up a mini dialog to enable/disable the set of previously granted permissions. In other words, this dialog may show any of three outcomes: “Camera allowed/blocked” or “Microphone allowed/blocked” or “Camera and microphone allowed/blocked”.

With this dialog, the permissions can only be changed as a whole. To individually reconfigure microphone or camera for the webpage, go back to the browser's settings area. Also of note is that the minidialog does not permit changing the device (the dropdown box does not react to anything in Chromium 115).

Granting AV capture (Android/Chrome)

Troubleshoot as described in the previous section about Chromium.

On Android, the browser has a third category of site-specific settings besides “Camera” and “Microphone”, namely “Sound”, that you need to check as well.

The popups for device access and site settings when tapping on the URL bar icon look similar to Chromium:

Camera device information (Linux)

The v4l2-ctl command-line utility can be used for a deeper technical view of available devices from the Video4Linux API. Our example system here has four V4L devices, which are: color capture, metadata channel, infrared capture, metadata channel.

# ls /dev/video*/dev/video0  /dev/video1  /dev/video2  /dev/video3
# v4l2-ctl -d /dev/video0 --allDriver Info:    Driver name      : uvcvideo    Card type        : FJ Camera: FJ Camera    Bus info         : usb-0000:00:14.0-7…Video input : 0 (Camera 1: ok)Format Video Capture:    Width/Height      : 640/480    Pixel Format      : 'YUYV' (YUYV 4:2:2)    Field             : None    Bytes per Line    : 1280    Size Image        : 614400    Colorspace        : sRGB    Transfer Function : Rec. 709    YCbCr/HSV Encoding: ITU-R 601…    Frames per second: 30.000 (30/1)…
# v4l2-ctl -d /dev/video1 --all…Format Metadata Capture:    Sample Format   : 'UVCH' (UVC Payload Header Metadata)    Buffer Size     : 10240
# v4l2-ctl -d /dev/video2 --allFormat Video Capture:    Width/Height      : 640/360    Pixel Format      : 'GREY' (8-bit Greyscale)    Field             : None    Bytes per Line    : 640    Size Image        : 230400    Colorspace        : sRGB    Transfer Function : Rec. 709    YCbCr/HSV Encoding: ITU-R 601    Quantization      : Default (maps to Full Range)…    Frames per second: 30.000 (30/1)…
# v4l2-ctl -d /dev/video3 --all…Format Metadata Capture:    Sample Format   : 'UVCH' (UVC Payload Header Metadata)

Capture device selection (Firefox)

Certain hardware may offer multiple capture modes and present them as independent or partially-independent selectable devices.

Of the four V4L devices our example system has, two produce images, and Firefox considers both the YUYV and the GREY output usable (and offers them through Javascript APIs to Meet). However, selecting the infrared camera with its monochrome output does not work without any explanation or error message, and selection always reverts back to the color device.

Capture device selection (Chromium)

You can configure this in Settings > “Privacy” > “Site settings” >

The dropdown for camera and microphone in the settings will only be visible when at least one webpage has already tried to exercise the audio/video API. Otherwise that dropdown box does not exist (in Chromium 115/Linux).

Of the four V4L devices our example system has, Chromium considers only the YUYV device selectable. Here too, the infrared camera was unusable.

Capture device selection (Meet)

Device selection can be made from the Meet interface settings.

Memory usage

$ ps auwwx | grep gromoxUSER       PID %CPU %MEM     VSZ     RSS COMMANDgromox    2273  0.0  0.1  226612   68804 /usr/libexec/gromox/delivery-queuegromox    2274  0.0  0.0  753708   46168 /usr/libexec/gromox/pop3gromox    2275  0.0  0.0 4294568   10652 /usr/libexec/gromox/timergromox    2329  0.0  0.3 2757436  239096 /usr/libexec/gromox/midbgromox    2551  0.0  1.7 2476752 1123772 /usr/libexec/gromox/imapgromox    2575  0.0  0.0 4425996   14016 /usr/libexec/gromox/eventgromox    2744  0.0  0.0  134888   12348 php-fpm: pool gromoxgromox    3017 53.5  2.3 6187236 1570196 /usr/libexec/gromox/httpgromox    3170  3.0  0.7 2169468  525840 /usr/libexec/gromox/zcoregromox    3191  0.0  0.1  701932   97788 /usr/libexec/gromox/delivery

glibc's malloc has a peculiar reservation strategy. The first call to malloc() inside any given thread allocates a large virtual memory block (128 MB on x86_64) to serve as a default heap for that thread. The higher the thread count, the higher the VSS/VSZ number.

In addition, because the heap is never really returned to the operating system under normal operation, if each thread (even in the best case scenario of serial execution) gets to work on sufficiently big datasets, all the individual heaps eventually get touched. On systems with memory overcommit enabled, the RSS number rises as memory is first touched; when overcommit is disabled, RSS will be accounted upfront on memory block allocation.

This wastefulness has been observed previously by other parties, e.g.

https://sourceware.org/bugzilla/show_bug.cgi?id=11261

https://bugs.openjdk.org/browse/JDK-8193521

https://github.com/JuliaLang/julia/issues/42566

Switching Gromox to jemalloc or tcmalloc did not show any notable reduction so far. If you like to experiment, you can do so by starting one or more Gromox services with the environment variables LD_PRELOAD=/usr/lib64/libjemalloc.so.2 or LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 set to make use of these alternate allocators. (On the grommunio Appliance, you need to install the libjemalloc2 and/or libtcmalloc4 packages first.)

# systemctl edit gromox-http
-- add to edit field --
[Service]Environment=LD_PRELOAD=/usr/lib64/libjemalloc.so.2

Message rules

Managing rules

MAPI allows to keep rules for every individual folder (cf. MS-OXORULE §1.3), but the way this is exposed by clients in their user interface varies.

Outlook (as of 2021) only supports editing rules for the default private store inbox, and for public folders.

To edit the rule table of the Inbox folder of the default private store in Outlook, choose File » Manage Rules & Alerts.

To edit the rule table of folders in public stores in Outlook, select the folder in the folder hierarchy view, call up the context menu, select "Properties". The properties dialog has a button "Folder Assistant".

"Folder Assistant" is greyed out for Exchange 2019 servers and enabled for Gromox servers.

grommunio-web only supports editing rules for the default private store inbox. (Settings » Rules)

To show the rule table of any folder in MFCMAPI, select the folder in the hierarchy view, call up the context menu, select "Other tables » Rules table". MFCMAPI does not support adding any rules and also cannot edit the PR_RULE_ACTIONS property.

Rule processor triggers

When a message is first saved into a public store folder through, the rules defined for that folder are executed for the message. (cf. OXORULE §1.3) This is lacking in gromox-zcore 2.3 and only implemented in gromox-emsmdb (OL/MSMAPI).

When a message is delivered into a private store folder, the rules defined for that folder are executed for the message. "Delivery" is an action which implies, but is distinct from, "Save message". Delivery is only invoked by gromox-delivery or gromox-mt2exm -D.

Rule execution caveats

OXORULE §1.3 pg. 11 ¶4 specifies that "the remaining rules continue to run against the moved message"

Exchange 2019 violates this OXORULE requirement. OP_MOVE action performs a copy of the message into the desired target folder, then schedules the original message for deletion. (A message sent to a private store inbox whose rule table has three OP_MOVEs produces three mails rather than one.)

Gromox 2.3: (same)

OXORULE §1.3 pg. 11 ¶5 specifies that "the server will evaluate the destination folder rules against the moved message after evaluating the remaining rules in the original folder"

Gromox 2.3: Destination folder rules are evaluated for the new message immediately once the copy is made (see above). Remaining rules in the original folder resume later (and are applied to the original message, not the copy).

Order of execution

Gromox 2.3: Processes the set of standard rules first (sorted by sequence number), then the set of extended rules (sorted by sequence number).

OXORULE gives some direction, but is vague: "same syntactic restrictions and semantic meanings of values apply as the respective property defined [for standard rules]" (§2.2.4)

MOVE/COPY availability for public folder rules: OXORULE §2.2.5.1 says they must not be used but this is a weird arbitrary limitation; Gromox allows it anyway. (But it should nevertheless be used with care due to loops. Gromox has loop detection.)

Outlook bugs and issues

Attachment size

Situation: When looking a mail that has attachments, the size reported next to the icon+filename appears inflated over the actual file size that will be saved to disk.

Cause: Outlook displays the value of the PR_ATTACH_SIZE MAPI property. This property is specified to not only include the file size, but also the metadata for the attachment.

Restoring softdeleted public folders

When a softdeleted public (sub-)folder is restored, the name is truncated to one character, even with EXC2019 server.

AutoDiscover diagnostics

When Outlook is running, there is an Outlook icon in the Windows taskbar's notification area. By pressing Ctrl+RightMouseBtn, a service menu can be brought up, which offers a "Test AutoDiscover" command for diagnosing problems from Windows. Known bugs: The dialog may ignore the contents of the password field and instead use a saved password or SSO, leading to potentially unanticipated HTTP 401 (Unauthorized) responses. If in doubt, use gromox-dscli.

SRV redirection warning

Situation: Outlook shows a redirection warning when the SRV record has a hostname different from the domain.

Text: “Allow this website to configure user@example.com server settings? https://mail.example.com/autodiscover/autodiscover.xml . Your account was redirected to this website for settings. You should only allow settings from sources you know and trust. [ ] Don't ask me about this website again.”

Cause: Questionable programming in Outlook and/or Windows's networking libraries. A SRV record has the same security considerations as a CNAME record. (Outlook also ignores the port number in the SRV record.)

Fixes/Workarounds: Report issues to Microsoft. Or use the always-accept checkbox. Deleting the DNS SRV record is a viable option too, because one can make a CNAME/A/AAAA-type autodiscover.example.com entry in the DNS zone instead.

Passwords with umlauts

Gromox conveys the available authentication mechanisms to clients via the WWW-Authentication header in HTTP responses. As of Gromox 2.17, "Basic" and "Negotiate" are supported. "Basic" is augmented by a charset parameter (RFC 7617 §2.1).

However, the Windows RPC and HTTP libraries ignore this parameter, and they also ignore the few UTF-8 options from the Control Panel's Internet Options dialog.

The RPC/HTTP libraries always transmit Basic authorization using the system default locale's codepage. In fact, if the password entered into the authorization dialog cannot be represented in that encoding, no Authorization header will be sent at all in the HTTP request.

Exchange Server interprets passwords received via the Basic authorization header as UTF-8 at first and, should the password validation fail, it will retry using the codepage of the default locale of the server system. This means that a Windows client using Japanese locale (codepage 932) will never be able to connect to an Exchange Server running with English locale (Codepage 1252) using Basic-type authentication.

Unlike Windows, installations of contemporary Linux systems exclusively use UTF-8. As such, there is no second charset that would make sense for a server process to try.

In Windows 10 and later, the Region settings in the (classic) Control Panel has a checkbox to switch the Narrow Encoding System APIs to interpret and emit strings and some other data as UTF-8, much like what Linux systems do. Be aware that changing the region has consequences for all unannotated data. For example, it influences how text editors will make guesses about the encoding of plain-text files.

Authentication via the Negotiate mechanism is believed to be mostly free from character set problems. Negotiate can contain GSS/SSO/NTLM tokens, and NTLM in particular is specified to use UCS-2LE/UTF-16LE for its challenge–response authentication, which gives non-ASCII characters an angle to survive.

Rules dialog not openable

RuleOrganizer is a FAI message in Inbox with PR_MESSAGE_CLASS="IPM.RuleOrganizer". If this message has no PR_RW_RULES_STREAM property, Outlook refuses to open the rules dialog. It issues a ropOpenStream call without MAPI_CREATE, which means it did not pass MAPI_CREATE to the IMessage::OpenProperty COM API either. Therefore, if the property is missing, OL will will not re-create it (which is stupid, because when the message is absent, it will re-create that).

Moreover, when the PR_RW_RULES_STREAM property exists but has size 0, the rules dialog immediately closes again, another bug.

Offending mailboxes can be repaired with the gromox-mbop -u abc@example.com clear-rwz command.

MFCMAPI table sort quirk

Sorting a table by clicking on a column header will make MFCMAPI use its own sorting rather than ropSortTable. Only the portion of rows that has already been loaded (ropQueryRows) will be sorted.

Outlook 2010/2013 specialties

Preface summary

At the end of May 2024, this document's German screenshots were slated for replacement with the English version. In that attempt, more weirdness protruded.

English OL2013 15.0.5125.1000 / MAPI 15.0.5449:

If AutoDiscover handler is offering MH: AutoDiscover completes, MAPI profile runs on MH, no traces of RPCH configuration found. All good.

ADH offering only RPCH: The wizard fails the Autodiscover stage. Eventually leads you over to manual setup mode.

Manual setup: The wizard is somehow completely unable to make a successful RPCH connection.

German OL2013 (exact version tbd):

AutoDiscover succeeds, you can also do manual setup, or switch to manual after AD has signalled success. Either way you go, the wizard somehow gets the idea it wants to talk to a magic hostname "SERVERS". You can end the wizard successfully and it believes it has a connection, but actually does not. The MAPI profile remains broken and the bogus RPC server name needs to be edited with MFCMAPI. Once that is done, it actually works very well over RPCH.

Control Panel

Open Control Panel and the E-Mail control widget and create a new profile. Alternatively, new profiles can be created when launching Outlook if and when it shows its profile selection dialog (requires that no profile be marked as default yet).

Special dialog for domain-joined accounts

When creating a new profile in Outlook, you may be presented with a dialog that has only two fields (name, email address), with the name field being filled in and grayed out already. This can happen if the computer is joined to an existing NT/ActiveDirectory domain.

If you were to leave those fields as-is, the wizard might skip AutoDiscover or use the AutoDiscover of the domain controller (especially when there is already an Exchange server). We have observed that, in such a domain, the wizard proceeds and uses the domain controller's name as the RPC server name, thereby causing requests to never reach the Gromox server.

Modifying the email address field value switches the dialog to present the usual four fields. This action would appear to drop the implied default to use the domain controller, which is a good thing.

AutoDiscover

When using automatic mode (i.e. the radiobox "E-mail Account") from the 4(!)-field dialog, the profile wizard proceeds to invoke AutoDiscover. Provided the DNS domain name resolves to a Gromox server, AutoDiscover should succeed, even if joined to an NT domain of the same name.

At this point, you may get a warning if you used a self-signed or otherwise not verifiable TLS certificate. If indeed your Gromox server uses such a certificate, that is a good sign that AutoDiscover did indeed reach the Gromox server.

Furthermore, there may be also be a second warning. The AutoDiscovery process uses a number of techniques, and one of them involves testing for a DNS entry wherein autodiscover. is prepended to the e-mail domain you entered. If that DNS entry indeed exists, but is not part of the TLS certificate, the wizard complains about a certifiace name mismatch.

With TLS squared away either with a proper certificate or ignoring the issue, AutoDiscover ought to succeed.

If you get a failure indication instead that an encrypted connection was not possible, that is usually an indication of a DNS or network issue, and attempting an unencrypted AutoDiscover request won't fix that.

Turning the attention back to the successful AutoDiscover dialog form (with the three green checkmarks), you have the option to switch to manual setup mode using the "Change account settings" checkbox in the lower left of the dialog. Doing so will make the wizard switch to the next dialog state, titled "Server settings".

Since this is a technical documentation exploring the quirks of Outlook, we recommend you do this for understanding the following descriptions. Continue reading below at section "RPC hostname troubles".

Manual Setup

If you choose the radiobox "Manual Setup", AutoDiscover will be skipped.

After choosing the Exchange server type radio box, you will proceed to the "Server Settings" view. You should input the server and user name. The OL2013 profile wizard defaults to using RPC over port 135, which is not supported by Gromox, and so using "Check Name" will not function just yet.

Instead, go to "More Settings" and its Security notebook page, and select "Anonymous Authentication" from the dropdown.

Next, goto More Setting's "Connection" notebook page, enable "Connect using HTTP", and call up the "Proxy Settings" subdialog.

Enter the server name again in the HTTP field, and switch from "NTLM Authentication" to "Basic Authentication".

You should enable both "On fast networks, connect using HTTP first" and "On slow networks, connect using HTTP first".

"Connect using HTTP first, then use TCP/IP" is a misnomer; what it really means "Connecting using RPCHTTP or MAPIHTTP first, then try RPC-over-TCP".

You can close the More Settings subdialog(s).

If you now use the "Check Name" feature, the server and user name field values should “resolve”, i.e. become underlined. The server name will also change to an uncanny value of SERVERS.

RPC hostname troubles

If AutoDiscover found the MH/RPCH transport just fine, the "Server Settings" dialog will show someguid@domain in the Server field and the email address in the username field. In addition, under "More Settings", there will only be three tabs and no way to call up the RPC proxy settings.

Now for the odd case with at least one OL2013 variant (German):

Whether you have done Manual Setup or reached this point through AutoDiscover, you will notice that the RPC server has been changed to the value SERVERS. We have no indication where this name comes from — searching prominent Windows DLLs, including, but not limited to, rpcrt4.dll, turns up no string of the sort, and it is incredibly hard to do an Internet search for the word because a common word was reused.

The server and email address are underlined and the "Check Names" button is grayed out, which normally indicates that the two field values have (supposedly) been successfully resolved.

You may finish the profile wizard at this point. Read on for more technical gore though…

Some Windows installations are fine with SERVERS. Some are not. We do not know exactly why, but one hypothesis is that some versions try to resolve the RPC server name ahead of the RPCHTTP proxy name. We did observe, with Wireshark, that name lookups were being done for SERVERS (NBNS, LLMNR and/or MDNS packets) are being emitted into the network.

By modifying the server or user name field again (e.g. remove last character and add the character back again), the field values go back to unresolved mode and the "Check Names" button becomes available again. When that check feature is used again, the server now magically resolves to a new value in the form of xxxxxxxx-xxxx-xxxx-xx-xxxxxxxxxxxx@hostname. While we know that this is a endpoint ID for an RPC proxy and we know where it originates from in the source code, it also does not help to get the mailbox connection going.

Repeatedly editing a field and using Check Names again, the profile wizard ping-pongs between SERVERS and the endpoint ID.

To really fix the wrong RPC server name, using MFCMAPI will become necessary.

MAPI profile data model

Inside the MAPI profile (a1 in the screenshots) are (at least) two services, one of which is for the mailbox, and another is for the addressbook. The EMSMDB service consists of three or four providers, these should correspond to the private mailbox, the public mailbox (if any), a transport provider (XP), and the global address book (GAB). The value SERVERS can be found in the properties PR_TEST_LINE_SPEED (0x662B001F), and 0x662A001F.

There is also PR_PROFILE_RPC_PROXY_SERVER (which contains the RPCHTTP/MAPIHTTP proxy) and PR_PROFILE_UNRESOLVED_SERVER (unsure why this is kept).

The value in the 0x662A001F property correlates with it. Changing this property in MFCMAPI changes it in the Control Panel dialog.

MFCMAPI shows the property as PR_TRANSFER_ENABLED, but that is not entirely accurate. Some property IDs are — unfortunately — reused between different components (e.g. profile vs. mailbox vs. address book), and MFCMAPI just does not evaluate the context in which it is used, and so prints the wrong name.

The value for PR_TEST_LINE_SPEED is of no consequence. It is said to be a special property to make emsmdb.dll always trigger a network request.

Changing SERVERS to the real host name makes mailbox access possible.

(Later versions of the connector such as from OL2021 do not create the 0x662A001F property at all anymore.)

Further reading

The Windows registry normally needs no changes, but for the curious, there are some options.

https://docs.microsoft.com/en-us/outlook/troubleshoot/profiles-and-accounts/unexpected-autodiscover-behavior

Technicalities with hanging connections

Outlook and tools like MFCMAPI usually invoke mapi32.dll functions from the same thread that also runs the user interface. The UI is blocked while MAPI functions execute. If the UI does not respond for a while, the desktop shell marks the window as unresponsive.

Modern connections to Exchange-style servers use HTTP (TCP), but even with a server sending TCP RST/FIN, the MSRPC libraries seem to take a while to notice. We surmise this is a side-effect of the historic design of DCERPC/MSRPC which allows for datagram transports — and where connection-oriented transports are an afterthought.

In Cached Mode, MAPI calls from application terminate at the OST file. The OST<->server synchronization runs in a separate thread. Therefore, connectivity interruptions do not normally affect the UI, though complex queries involving the OST contents (opening a folder with 50000 mails) may still.

In MFCMAPI with an online-mode MAPI profile, on connectivity interruption it can be observed that the store handle "shuts down" and a number of subsequent MAPI calls return a network error, until such a time that mapi.dll or the program decides to effectively re-login and obtain a new, valid store handle. (In doing so, MFCMAPI crashes sometimes. Outlook seems to handle this better and live on.)

PHP Environment

opcache

The opcache extension mis-executes the ZEND_TYPE_CHECK opcode in at least PHP 8.0.25 and causes a vital PHP expression, is_resource($x), to curiously yield false even when $x is a valid resource. The issue occurs in the same spot in grommunio-web, and is reliably reproducible, but we do not know why exactly. g-web is a big program and attempts to replicate the problem with a smaller program have been unsuccessful to date.

mapi.so checks whether opcache.so is present and enabled, and if so, refuses operation. You must disable opcache.

Details:

We find that the Zend engine treats the PHP is_resource(...) function call specially ([1] https://github.com/php/php-src/blob/master/Zend/zend_compile.c#L4497_):

} else if (zend_string_equals_literal(lcname, "is_resource")) {    return zend_compile_func_typecheck(result, args, IS_RESOURCE);

and that Zend compiles it to a ZEND_TYPE_CHECK opcode with extended_value being (1 << IS_RESOURCE) ([2]).

opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);if (type != _IS_BOOL) {    opline->extended_value = (1 << type);} else {    opline->extended_value = (1 << IS_FALSE) | (1 << IS_TRUE);}

When the two lines shown in the first block are removed, the is_resource($x) expression would instead be compiled to a ZEND_INIT_FCALL opcode ([3]) and execution would eventually land in the C function corresponding to is_resource ([4]).

static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type){    if (Z_TYPE_P(arg) == type) {    ...

Summarizing our observations:

Unmodified Zend VM, php-opcache disabled, is_resource becomes ZEND_TYPE_CHECK: good

Unmodified Zend VM, php-opcache enabled, is_resource becomes ZEND_TYPE_CHECK: bad

Modified Zend VM, php-opcache enabled, is_resource becomes ZEND_INIT_FCALL: good

We conclude that php-opcache induces a problem with respect to the ZEND_TYPE_CHECK opcode.

There is a... peculiar comment in php-opcache (MAY_BE_RESOURCE is the same as 1 << IS_RESOURCE) ([5]) that could(?) be relevant:

case ZEND_TYPE_CHECK:    if (opline->extended_value == MAY_BE_RESOURCE) {        // TODO: support for is_resource() ???        break;    }

Search

Different search results

Outlook and g-web use different search filters (MAPI restrictions) under different circumstances, so it is possible they yield different results.

Default restriction of Outlook (online mode) when Quick Search (DE:Sofortsuche) is used on Inbox (22 conditions, OR-ed):

19 properties tested for the user-defined search terms:

0037001fh PR_SUBJECT

0042001fh PR_SENT_REPRESENTING_NAME

0065001fh PR_SENT_REPRESENTING_EMAIL_ADDRESS

0c1a001fh PR_SENDER_NAME

0c1f001fh PR_SENDER_EMAIL_ADDRESS

0e02001fh PR_DISPLAY_BCC

0e03001fh PR_DISPLAY_CC

0e04001fh PR_DISPLAY_TO

1000001fh PR_BODY

PSETID_Appointment,LID=8208h PidLidLocation

PSETID_Common,LID=85a4h PidLidToDoTitle

PSETID_Sharing,LID=8a04h PidLidSharingRemotePath

PSETID_Sharing,LID=8a05h PidLidSharingRemoteName

PSETID_Sharing,LID=8a07h PidLidSharingInitiatorName

PSETID_Sharing,LID=8a0fh PidLidSharingLocalName

PSETID_Sharing,LID=8a2fh PidLidSharingRemoteComment

PSETID_Sharing,LID=8a51h PidLidSharingBrowseUrl

PS_PUBLIC_STRINGS,NAME=Keywords (Categories)

PSETID_UnifiedMessaging,NAME=UMAudioNotes

3 instances of a contradictory (nonsensical) condition: RES_AND{RES_EXIST{PR_LAST_MODIFCATION_TIME}, RES_NOT{RES_EXIST{PR_LAST_MODIFICATION_TIME}}}

Default restriction of Outlook (online mode) for quick search in the trash folder (44 conditions):

19+3 from above, plus 22 more properties:

3001001fh PR_DISPLAY_NAME

3a08001fh PR_BUSINESS_TELEPHONE_NUMBER

3a09001fh PR_HOME_TELEPHONE_NUMBER

3a16001fh PR_COMPANY_NAME

3a17001fh PR_COMPANY_NAME

3a18001fh PR_DEPARTMENT_NAME

3a1b001fh PR_BUSINESS2_TELEPHONE_NUMBER

3a1c001fh PR_MOBILE_TELEPHONE_NUMBER

PSETID_Address,LID=8005h PidLidFileUnder

PSETID_Address,LID=801ah PidLidHomeAddress

PSETID_Address,LID=801bh PidLidWorkAddress

PSETID_Address,LID=801ch PidLidOtherAddress

PSETID_Address,LID=802ch PidLidYomiFirstName

PSETID_Address,LID=802dh PidLidYomiLastName

PSETID_Address,LID=802eh PidLidYomiCompanyName

PSETID_Address,LID=8083h PidLidEmail1EmailAddress

PSETID_Address,LID=8093h PidLidEmail2EmailAddress

PSETID_Address,LID=80a3h PidLidEmail3EmailAddress

PSETID_Task,LID=811fh PidLidTaskOwner

PSETID_Common,LID=8539h PidLidCompanies

PSETID_Common,LID=853ah PidLidContacts

PSETID_Log,LID=8700h PidLidLogType

If OL detects PR_CI_SEARCH_ENABLED on the store, it instead uses:

1 property tested for the user-defined search terms

0eaf001fh PR_SEARCH_ALL_INDEXED_PROPS

If OL is to search the entire mailbox, further conditions are added:

message class must be one of: IPM.Document, IPM.Note, IPM.Post, IPM.Recall, IPM.Schedule, IPM.Sharing, IPM.TaskRequest REPORT

When using the "Extended Search" (DE:Erweiterte Suche) dialog in OL, PR_SEARCH_ALL_INDEXED_PROPS is not used.

Outlook (Cached Mode) might yet use another filter.

Default filter of grommunio-web:

41 properties across 8 classes:

37001fh PR_SUBJECT

42001fh PR_SENT_REPRESENTING_NAME

65001fh PR_SENT_REPRESENTING_EMAIL_ADDRESS

c1a001fh PR_SENDER_NAME

c1f001fh PR_SENDER_EMAIL_ADDRESS

e03001fh PR_DISPLAY_CC

e04001fh PR_DISPLAY_TO

1000001fh PR_BODY

3001001fh PR_DISPLAY_NAME

3a02001fh PR_CALLBACK_TELEPHONE_NUMBER

3a05001fh PR_GENERATION

3a08001fh PR_BUSINESS_TELEPHONE_NUMBER

3a09001fh PR_HOME_TELEPHONE_NUMBER

3a16001fh PR_COMPANY_NAME

3a1a001fh PR_PRIMARY_TELEPHONE_NUMBER

3a1b001fh PR_BUSINESS2_TELEPHONE_NUMBER

3a1c001fh PR_MOBILE_TELEPHONE_NUMBER

3a1d001fh PR_RADIO_TELEPHONE_NUMBER

3a1e001fh PR_CAR_TELEPHONE_NUMBER

3a1f001fh PR_OTHER_TELEPHONE_NUMBER

3a21001fh PR_BEEPER_TELEPHONE_NUMBER

3a23001fh PR_PRIMARY_FAX_NUMBER

3a24001fh PR_BUSINESS_FAX_NUMBER

3a25001fh PR_HOME_FAX_NUMBER

3a2c001fh PR_TELEX_NUMBER

3a2e001fh PR_ASSISTANT_TELEPHONE_NUMBER

3a2f001fh PR_HOME2_TELEPHONE_NUMBER

3a45001fh PR_DISPLAY_NAME_PREFIX

3a4b001fh PR_TTYTDD_PHONE_NUMBER

3a57001fh PR_COMPANY_MAIN_PHONE_NUMBER

PSETID_Address,LID=8005h PidLidFileUnder

PSETID_Address,LID=801ah PidLidHomeAddress

PSETID_Address,LID=801bh PidLidWorkAddress

PSETID_Address,LID=801ch PidLidOtherAddress

PSETID_Address,LID=8083h PidLidEmail1EmailAddress

PSETID_Address,LID=8093h PidLidEmail2EmailAddress

PSETID_Address,LID=80a3h PidLidEmail3EmailAddress

PSETID_Task,LID=33055 PidLidTaskOwner

PSETID_Appointment,LID=33288 PidLidLocation

PSETID_Common,LID=34105 PidLidCompanies

PS_PUBLIC_STRINGS,NAME=Keywords (Categories)

Classes:

IPM.Appointment, IPM.Contact, IPM.DistList, IPM.Note (standard message), IPM.Schedule, IPM.StickyNote, IPM.Task, REPORT.IPM.Note

Class selection thus skips over e.g. (non-exhaustive list):

IPM.Activity (journal), IPM.Post (public folder post), SMIME messages

Since BCC is not on the list, Drafts with an otherwise matching BCC entry would get skipped

The MFCMAPI utility can be used to inspect the search criteria (filter).

Sent Folder

As per MSDN docs, mail clients can set the MAPI property PR_SENTMAIL_ENTRYID and point to a folder where a message should be moved once it has been sent. Note that this is mutually exclusive with PR_DELETE_AFTER_SUBMIT (only one action can be performed).

Database check

Timing anecdote: The entire exchange.sqlite3 file is read. On an AMD 5950X CPU with sqlite 3.46 (runs single-threaded), the processing speed from an in-memory file is about 104 MB/s. Thus, slow storage and huge mailboxes influence the time the operation takes in practice.

# sqlite3 /var/lib/gromox/domain/1/exmdb/exchange.sqlite3sqlite> pragma integrity_check;integrity_check--------------------------------------------------row 202171 missing from index state_username_indexrow 208269 missing from index state_username_indexrow 208282 missing from index state_username_indexrow 208284 missing from index state_username_indexrow 225182 missing from index state_username_indexrow 226595 missing from index state_username_indexTree 33990 page 33990 cell 260: invalid page number 4053928964Tree 33990 page 33990 cell 259: invalid page number 4050783236Tree 33990 page 33990 cell 255: invalid page number 333502732Multiple uses for byte 1240 of page 33990

Recovery

When (just) indices are broken, the file may be recreated when gromox-http is not actively using the database:

systemctl stop gromox-httpcd /var/lib/gromox/domain/1/exmdb/(echo "PRAGMA foreign_keys=0;"; sqlite3 exchange.sqlite3 ".recover") | sqlite3 new.dbchmod u=rw,g=rw new.dbchown grommunio:gromox new.dbmv exchange.sqlite3 exchange.sqlite3.oldmv new.db exchange.sqlite3systemctl restart gromox-http

Terminal window

We turn off foreign keys (FK) here temporarily because recovery can process tables in an order that is not supported by FK constraints.

(There is also an alternate command for .recover:)

sqlite3 exchange.sqlite3 ".clone new.db"

Terminal window

The efficacy of the recover/clone commands depends on the brokenness level of the database file. It will repair structural problems (as far as it is able to) at the SQLite level, but the recovered data may still contain logical problems as a whole, e.g. two users with the same ID.

Consult with grommunio Support. Keep backups.

Update Cycle

RH vs SUSE

“ We do not want to update all that often, so we are choosing RHEL/CentOS/Alma/etc. [in favor of SLE] ”

RHEL (and its derivatives) actually release a lot more service packs over time, and the service packs' individual lifetime is also shorter:

SP | Release | Last repo change | Lifetime
AlmaLinux 8.4 | 2021-05-26 | 2021-11-22 | 181 days
AlmaLinux 8.5 | 2021-11-12 | 2024-09-28 | 320 days
AlmaLinux 8.6 | 2024-05-12 | 2024-11-03 | 176 days
AlmaLinux 9.0 | 2024-05-26 | 2024-11-03 | 162 days

SP | Release | End of Support | Lifetime
SLE 15.1 | 2019-06-21 | 2021-01-31 | 591 days
SLE 15.2 | 2020-06-22 | 2021-12-31 | 558 days
SLE 15.3 | 2021-06-21 | 2024-12-31 | 559 days

For admins with an aversion to periodic invocation of the updater, the update cadence is in favor of a SUSE-based distribution.

Virtualization

VirtualBox Classic BIOS

Use F12 to call up the boot menu.

When booting from a CD-ROM and choosing "Boot local disk", VirtualBox hangs. This seems to be a problem exclusive to the VirtualBox implementation of Classic BIOS (does not occur on VMware platforms, or when using VBox EFI).

The VBE implementation offers modes from 320×200 to 1600×1200 in the default set (and some more via private INT 10h function 5642h, from 640×480 to 2560×1920, but this is not used by GRUB).

Default firmware resolution is 640×480.

If GRUB is set to use GRUB_GFXMODE=auto (cf. /etc/default/grub), which makes it simply retain that resolution. (This in contrast to e.g. choosing the maximum available resolution.)

A manual list of resolutions always inconveniences at least one concrete system, so we will leave the Grommunio installation media and default system settings at auto. You can change the resolution in existing systems to a suitable size.

VirtualBox EFI

Use F2 to call up the boot menu.

The EFI GOP driver supports a plethora of modes from 640×480 to 7680×4320.

Default firmware resolution is 1024×768.