While Thunderbird is primarily recognized as an email client, it also features a unique calendar mode. Distinctively, this calendar mode is designed as a web page and is seamlessly delivered through Chrome. Due to this tight integration, many users might not even realize that Thunderbird functions as a local web application. This document is intended to offer useful tips for maximizing the use and configuration of the Thunderbird calendar.
By default, Thunderbird’s date formatting adheres to the locale setting of the operating system. For instance, if you’re using the locale en_us.UTF8
, you’ll encounter dates in the format “2023/07/30”. But if you’re utilizing the German locale, it’ll display as “30.07.2023”. Now, what if you wish to employ the ISO format while retaining the German language setting? Contrary to the Evolution email client, Thunderbird’s standard configuration dialog doesn’t readily support this preference.
Solution 1: Opt for a locale that supports your desired short date format.
Solution 2: This is specifically for users with Thunderbird version 91 or later:
Open the Config Editor
by navigating to Preferences > General. Scroll down to the bottom of the page.
Adjust the setting intl.regional_prefs.use_os_locales
to false
.
intl.regional_prefs.use_os_locales = false
Next, alter intl.date_time.pattern_override.date_short
to the string value “yyyy-MM-dd
”.
intl.date_time.pattern_override.date_short = yyyy-MM-dd
For a comprehensive guide on this topic, please refer to Mozilla’s official guide.
Although users can adjust the font and its size in the ‘Preferences General’ setting of the Thunderbird application, it doesn’t affect the calendar. For instance, on Debian 12 Bookworm under MATE, the default font is Cantarell at a size of 17, relatively large. To display four calendar entries spaced 15 minutes apart within a single hour, users either need to significantly zoom in or the display splits into two columns. Notably, unlike in Evolution, setting the time division to 15 minutes doesn’t alter this behavior.
As there’s no direct configuration option to adjust the calendar font or size, users need to employ a workaround by modifying the application’s underlying CSS.
To identify the current settings and values, initiate Thunderbird with web tools using:thunderbird --devtools
Enable a Custom CSS File
Navigate to the Config Editor
and configure toolkit.legacyUserProfileCustomizations.stylesheets
to true
.
toolkit.legacyUserProfileCustomizations.stylesheets = true
Set Up an Empty CSS File
Create an empty file named userChrome.css
inside the chrome
directory.
cd ~/.thunderbird/*.default-default
mkdir chrome
cd chrome
touch useChrome.css
Test the CSS Integration
To verify Thunderbird’s use of the file, add a test CSS rule. For instance, adjusting the size of the calendar day header:
.day-column-container {
font-size: 12px;
}
It’s advisable to utilize the development tools and the inspector to check computed values before and after modifications to discern any changes. However, be mindful that the application’s HTML and CSS might evolve over time.
Address the Font Size Issue
To remedy the specific font size concern, reduce the font size from 17.333px to 16px and eliminate some padding. The original .day-column-container
setting can be discarded.
.calendar-item-flex {
padding-top: 0px !important;
padding-bottom: 0px !important;
row-gap: 2px !important;
}
.event-name-label {
font-weight: 400 !important;
font-size: 16px;
}
Restart Required
Remember, any modifications necessitate a Thunderbird restart for changes to take effect.
For additional guidance, refer to:
For many users, Thunderbird’s graphical interface is the go-to method for adding calendars. While efficient, this method doesn’t lend itself to replicating configurations across multiple machines, especially if you need consistency in test environments. The solution? Automate this process using Ansible.
However, using Ansible (or any other configuration management tool) for Thunderbird introduces a challenge: Thunderbird uses a hashed location to store its configuration. For instance, the main configuration resides in ~/.thunderbird
. Within this directory, the file profiles.ini
contains a section Profile0
with a Path
key pointing to the real configuration. For clarification:
...
[Install7DFCE75BB80C198C]
Default=oGao5Tha.default-default
Locked=1
[Profile0]
Name=default-default
IsRelative=1
Path=oGao5Tha.default-default
...
On Debian, the Profile1
profile is recognized as the default
profile. But it’s the default-default
profile that retains all the configuration.
To determine the current configuration path, you can use the script ansible-thunderbird-cfg-path-get
:
#!/usr/bin/bash
export DIR=/home/USER/.thunderbird
cat $DIR/p*.ini|grep 'Pa.*-default'|sed -e "s%Path=%$DIR/%"
When executed, the output might resemble:
/home/USER/.thunderbird/oGao5Tha.default-default
The provided Ansible playbook performs the following functions:
user.js
configuration file.For this playbook to function correctly:
prefs.js
.USER
placeholder with the appropriate user name.ansible_cfg_path
to the location where your playbooks, templates, and scripts are stored. The key directories are: bin
(scripts), pb
(playbooks), and tpl
(templates).user.js
as it might overwrite your existing configurations.Below is the enhanced playbook:
hosts: localhost
gather_facts: no
vars:
ns: thunderbird
ansible_cfg_path: /srv/ansible
packages:
- thunderbird
caldav_calendars:
- uuid: work
color: "#1c71d8"
refresh: 5
name: Work
uri: https://example.org/rad/USER/work
username: USER
imip:
identity: id1
tasks:
- name: "{{ ns }}: Install and update Thunderbird"
package:
name: "{{ packages }}"
state: latest
- name: "{{ ns }}: Create a temporary directory for calendar files"
tempfile:
state: directory
register: tempdir
- name: "{{ ns }}: Retrieve the Thunderbird configuration path"
command: "{{ ansible_cfg_path }}/bin/ansible-thunderbird-cfg-path-get"
register: config_path
changed_when: False
- name: "{{ ns }}: Display the configuration path (optional)"
debug:
var: config_path.stdout
- name: "{{ ns }}: Generate calendar configuration files"
template:
src: "{{ ansible_cfg_path }}/tpl/HOME/thunderbird/caldav_calendar.js"
dest: "{{ tempdir.path }}/caldav_calendar_{{ calendar.uuid }}.js"
mode: 'a'
loop: "{{ caldav_calendars }}"
loop_control:
loop_var: calendar
when: config_path.stdout is defined and config_path.stdout != ''
- name: "{{ ns }}: Combine individual files into user.js"
assemble:
src: "{{ tempdir.path }}/"
dest: "{{ config_path.stdout }}/user.js"
when: config_path.stdout is defined and config_path.stdout != ''
The is the template tpl/HOME/thunderbird/caldav_calendar.js
:
// {{ calendar.name }}
user_pref("calendar.registry.{{ calendar.uuid }}.cache.enabled", true);
user_pref("calendar.registry.{{ calendar.uuid }}.calendar-main-default", true);
user_pref("calendar.registry.{{ calendar.uuid }}.calendar-main-in-composite", true);
user_pref("calendar.registry.{{ calendar.uuid }}.color", "{{ calendar.color }}");
user_pref("calendar.registry.{{ calendar.uuid }}.disabled", false);
user_pref("calendar.registry.{{ calendar.uuid }}.imip.identity.key", "{{ calendar.imip.identity }}");
user_pref("calendar.registry.{{ calendar.uuid }}.name", "{{ calendar.name }}");
user_pref("calendar.registry.{{ calendar.uuid }}.notifications.times", "");
user_pref("calendar.registry.{{ calendar.uuid }}.readOnly", false);
user_pref("calendar.registry.{{ calendar.uuid }}.refreshInterval", "{{ calendar.refresh }}");
user_pref("calendar.registry.{{ calendar.uuid }}.suppressAlarms", false);
user_pref("calendar.registry.{{ calendar.uuid }}.type", "caldav");
user_pref("calendar.registry.{{ calendar.uuid }}.uri", "{{ calendar.uri }}");
user_pref("calendar.registry.{{ calendar.uuid }}.username", "{{ calendar.username }}");
By following this playbook, you can seamlessly integrate multiple CalDAV calendars into Thunderbird across various machines for one user.
Adding ICS calendars to Thunderbird through Ansible closely mirrors the process for adding CalDAV calendars, albeit with some variations in parameters. This section builds upon the Ansible playbook discussed in the previous section. If you haven’t reviewed it yet, it’s recommended to do so before proceeding.
The primary distinctions between ICS and CalDAV calendars are as follows:
ICS calendars are read-only. (In this example)
They don't have an associated identity. (In this example)
They come without alarms. (In this example)
They possess the distinct type 'ics'
For this configuration, we employ a template named ics_calendar.js
.
Below is the comprehensive playbook:
# pb/thunderbird.yaml
---
- hosts: localhost
gather_facts: no
vars:
ns: thunderbird
ansible_cfg_path: /srv/ansible
packages:
- thunderbird
caldav_calendars:
- uuid: 03-work
color: "#1c71d8"
refresh: 5
name: Work
uri: https://example.org/rad/USER/work
username: USER
imip:
identity: id1
ics_calendars:
- uuid: 10-german-holidays
color: "#f5c211"
name: Feiertage
uri: URL.ics
tasks:
- name: "{{ ns }}: Install and update packages"
package:
name: "{{ packages }}"
state: latest
- name: "{{ ns }}: Get Thunderbird configuration path"
command: "{{ ansible_cfg_path }}/bin/ansible-thunderbird-cfg-path-get"
register: config_path
changed_when: False
- name: "{{ ns }}: Create temporary directory for calendar files"
file:
path: "{{ config_path.stdout }}/ansible/calendars"
state: directory
owner: USER
group: USER
mode: '0750'
recurse: yes
register: tempdir
- name: "{{ ns }}: Show the configuration path (debugging, can be removed)"
debug:
var: config_path.stdout
- name: "{{ ns }}: Generate individual CalDAV calendar files"
template:
src: "{{ ansible_cfg_path }}/tpl/HOME/thunderbird/caldav_calendar.js"
dest: "{{ tempdir.path }}/caldav_calendar_{{ calendar.uuid }}.js"
loop: "{{ caldav_calendars }}"
loop_control:
loop_var: calendar
when: config_path.stdout is defined and config_path.stdout != ''
- name: "{{ ns }}: Generate individual ICS calendar files"
template:
src: "{{ ansible_cfg_path }}/tpl/HOME/thunderbird/ics_calendar.js"
dest: "{{ tempdir.path }}/ics_calendar_{{ calendar.uuid }}.js"
loop: "{{ ics_calendars }}"
loop_control:
loop_var: calendar
when: config_path.stdout is defined and config_path.stdout != ''
- name: "{{ ns }}: Assemble user.js from individual calendar files"
assemble:
src: "{{ tempdir.path }}/"
dest: "{{ config_path.stdout }}/user.js"
when: config_path.stdout is defined and config_path.stdout != ''
The is the template tpl/HOME/thunderbird/ics_calendar.js
:
// {{ calendar.name }}
user_pref("calendar.registry.{{ calendar.uuid }}.cache.enabled", true);
user_pref("calendar.registry.{{ calendar.uuid }}.calendar-main-in-composite", true);
user_pref("calendar.registry.{{ calendar.uuid }}.color", "{{ calendar.color }}");
user_pref("calendar.registry.{{ calendar.uuid }}.disabled", false);
user_pref("calendar.registry.{{ calendar.uuid }}.imip.identity.key", "");
user_pref("calendar.registry.{{ calendar.uuid }}.name", "{{ calendar.name }}");
user_pref("calendar.registry.{{ calendar.uuid }}.notifications.times", "");
user_pref("calendar.registry.{{ calendar.uuid }}.readOnly", true);
user_pref("calendar.registry.{{ calendar.uuid }}.refreshInterval", "600");
user_pref("calendar.registry.{{ calendar.uuid }}.suppressAlarms", true);
user_pref("calendar.registry.{{ calendar.uuid }}.type", "ics");
user_pref("calendar.registry.{{ calendar.uuid }}.uri", "{{ calendar.uri }}");
Ensure that you update placeholders such as USER, URL accordingly. If you alter the UUID, also remember to delete files from the cache directory located at {{ config_path.stdout }}/ansible/calendars
.
A notable modification from the previous section’s playbook is the replacement of tempdir
with a manually selected cache directory. This adjustment was made because with multiple Ansible runs would label the result as ‘ok’ instead of ‘changed’. The latter would have been the case with a tempdir
that is constantly changing.
By following this playbook, you can seamlessly integrate multiple CalDAV and ICS calendars into Thunderbird across various machines for one user.
To modify the calendar font size in Thunderbird using Ansible, follow the steps outlined below:
userChrome.css
file to the chrome subdirectory.toolkit.js
is added to the ansible directory.user.js
.Here’s a snippet illustrating the process:
---
- hosts: localhost
gather_facts: no
vars:
ns: thunderbird
user_cal: 'c'
user_sys: 'c'
ansible_cfg_path: /srv/g/g.c8i.org/an
thunderbird_src: "HOME/thunderbird/UUID.default-default"
fls_src: "{{ ansible_cfg_path }}/fls/{{ thunderbird_src }}"
tasks:
- name: "{{ ns }}: Get Thunderbird configuration path"
command: "{{ ansible_cfg_path }}/bin/ansible-thunderbird-cfg-path-get"
register: config_path
changed_when: False
- name: "{{ ns }}: Ensure chrome directory exists in configuration"
file:
path: "{{ config_path.stdout }}/chrome"
state: directory
owner: "{{ user_sys }}"
group: "{{ user_sys }}"
mode: '0755'
- name: "{{ ns }}: Copy userChrome.css to thunderbird configuration"
copy:
src: "{{ fls_src }}/chrome/userChrome.css"
dest: "{{ config_path.stdout }}/chrome/userChrome.css"
owner: "{{ user_sys }}"
group: "{{ user_sys }}"
mode: '0644'
- name: "{{ ns }}: Create temporary directory for ansible files"
file:
path: "{{ config_path.stdout }}/ansible"
state: directory
owner: "{{ user_sys }}"
group: "{{ user_sys }}"
mode: '0755'
register: tempdir
- name: "{{ ns }}: Generate toolkit configuration for userChrome.js"
copy:
src: "{{ fls_src }}/ansible/toolkit.js"
dest: "{{ tempdir.path }}/toolkit.js"
owner: "{{ user_sys }}"
group: "{{ user_sys }}"
mode: '0644'
- name: "{{ ns }}: Assemble user.js from individual calendar files"
assemble:
src: "{{ tempdir.path }}/"
dest: "{{ config_path.stdout }}/user.js"
when: config_path.stdout is defined and config_path.stdout != ''
The {{ fls_src }}/ansible/toolkit.js
file as the following content:
// Enable ~/.thunderbird/UUID.default-default/chrome/userChrome.css
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
The Change the Date Format section elucidates how to utilize user.js
to configure Thunderbird. This section leverages the Ansible playbook from the preceding section to automate this process.
- name: "{{ ns }}: Generate custome date configuration"
copy:
src: "{{ fls_src }}/ansible/date.js"
dest: "{{ tempdir.path }}/date.js"
owner: "{{ user_sys }}"
group: "{{ user_sys }}"
mode: '0644'
The file {{ fls_src }}/ansible/date.js
contains the following settings:
// Setting custom date format: yyyy-MM-dd
user_pref("intl.regional_prefs.use_os_locales", false)
user_pref("intl.date_time.pattern_override.date_short", "yyyy-MM-dd")
Version | Date | Notes |
---|---|---|
0.1.8 | 2023-07-21 | Add section Change the Date Format with Ansible |
0.1.7 | 2023-07-20 | Add Ansible playbook snippet for userChrome.css |
0.1.6 | 2023-07-19 | Improve playbooks (fixes, line width) |
0.1.5 | 2023-07-15 | Fix missing color in CalDAV template |
0.1.4 | 2023-07-14 | Add section about adding a ICS calendar (Ansible) |
0.1.3 | 2023-07-13 | Add section about adding a CalDAV calendar (Ansible) |
0.1.2 | 2023-07-12 | Fix formatting |
0.1.1 | 2023-07-10 | Add section about changing calendar font size |
0.1.0 | 2023-07-07 | Initial release |