About this Documentation¶
This document tries to cover all aspects of how to create a provider add-on for TbSync to extends its sync capabilities.
Note
All TbSync provider add-ons are currently designed as bootrapped extensions, for which support is probably going to be dropped from Thunderbird at some time. We are working on migrating the TbSync API into a WebExtension API, so - hopefully - all provider add-ons can be converted into future proof WebExtensions without much effort.
- Introduction
- This section gives a short introduction to TbSync and its provider concept.
- Getting Started
- As promised by the name, this section gets you started by explainig how to create your own basic provider add-on in just a couple of minutes and gives instructions to get it running in Thunderbird.
- Implementing the Provider Classes
- Learn how to interact with TbSync.
Introduction¶
What is TbSync ?¶
TbSync is a central user interface to manage cloud accounts and to synchronize their contact, task and calendar information with Thunderbird. Its main objective is to simplify the setup process for such accounts and to improve the user experience by creating a common place to manage them.

Further details can be found in the wiki of the TbSync project.
What is a TbSync Provider Add-on ?¶
TbSync itself is just the manager UI and does not provide any sync capabilities on its own. But it provides an API for other add-ons to hook into TbSync. Such add-ons, which use this API and add sync capabilities are called TbSync provider add-ons. The following provider add-ons are currently available:
Getting Started¶
Generating a Basic TbSync Provider Add-on¶
Head over to
https://github.com/jobisoft/Provider-4-TbSync
and clone the provider add-on template repository. If you have a GitHub account yourself, you can simply add a copy of the provider add-on template to your own account.
After you have all the files on disc, run
./setup.py
which will ask you a couple of questions to setup the provider add-on for you. After that is done, you can install your own provider add-on in Thunderbird 68. Just zip the project folder and install the file using the gear menu in the Thunderbird add-on manager:
To see your own provider add-on in action, you need to install the latest version of TbSync from the so called beta release channel for Thunderbird 68.
https://github.com/jobisoft/TbSync/wiki/Get-the-latest-TbSync-version#beta-release-channel
Please make sure, that you uninstall any other TbSync provider add-on or switch to their version from the beta release channel as well. Your own provider add-on should then show up in the “Add new account” menu of TbSync:
Once your TbSync provider add-on is stable and released to addons.thunderbird.net, it can be added as a standard entry to the “Add new account” menu of TbSync, so all TbSync users will learn about it and get directed to its add-on page. For example this is what users see, when they try to create an ActiveSync account, but the provider add-on for ActiveSync is not yet installed:
Directory Structure of the Generated Provider Add-on¶
These are the important files and folders of the generated provider add-on:
Project
├── bootstrap.js
├── chrome.manifest
├── manifest.json
├── _locales
│ └── en-US
│ ├── messages.json
│ ├── provider.dtd
│ └── provider.strings
├── skin
│ ├── logo16.png
│ └── logo32.png
│ └── logo48.png
└── content
├── provider.js
└── manager
├── createAccount.js
├── createAccount.xul
├── editAccountOverlay.js
└── editAccountOverlay.xul
The author suggests to not rename files or folders, to not break the add-on. The following list provides an overview:
- bootstrap.js
- This file is registering your provider add-on with TbSync. The generated file should work out of the box.
- manifest.json
- The main configuration file for your add-on. Further details about this file can be found in the MDN documentation. The generated file should work out of the box.
- chrome.manifest
- An additional configuration file for your add-on. You probably only have to change it, when adding further translations (locales).
- _locales
Folder containing files to translate your add-on into different languages. Add a subfolder for each language and register them in
chrome.manifest
. The name of the folder must not be changed.- en-US/messages.json
- Localization for entries in
manifest.json
. Check the MDN documentation for more details. The name of the file must not be changed. - en-US/provider.strings
- Localization for your add-on, which can be accessed from JavaScript. The name of the file may be anything you like, but it must be announced via
Base.getStringBundleUrl()
as TbSync needs to access some of your localized strings. In paticular error messages and synchronization states your add-on is using. - en-US/provider.dtd
- Deprecated localization for XUL files of your add-on. Try to avoid its usage and instead set the localized labels of XUL/HTML elements via JavaScript. The generated provider add-on is using this in
createAccount.xul
andeditAccountOverlay.xul
.
- skin
- Folder containing all your additional resources like images and CSS files. It exists for historical reasons and the author is used to that approach. The generated provider add-on also stores its logo files there. If you change their names, please also update your manifest.json and your implementation of
Base.getProviderIcon()
. - content
Folder containing your add-ons source files.
- provider.js
- File containing your implementation of the
Base()
class and a few other classes, depending on what your add-on is supposed to do. See Implementing the Provider Classes for more details. - manager
- Folder containing resources used be the manager UI. In paticular the XUL file for the Create new account dialog of your provider add-on (see
Base.getCreateAccountWindowUrl()
) and the XUL file containing your tabs for the Edit account dialog (seeBase.getEditAccountOverlayUrl()
).
Implementing the Provider Classes¶
The content of file provider.js
will be loaded into the provider namespace and is the central starting point to implement the TbSync provider classes. The provider namespace is build using the short provider identifier selected during the initial setup of the provider add-on:
TbSync.providers.<short provider identifier>
- Base Class
- Implementing the
Base()
class defines, where TbSync can find certain things, like icons, XUL files for different dialogs or localized string definitions. It also defines, what properties the provider needs in the account and folder database and what should happen, if an account is being synchronized. - FolderList Classes
A central part of the TbSync manager UI is the folder list, which displays available resources discovered by the provider and their synchronization status. It even allows interaction via additional buttons or context menus.
Either the
FolderList()
class or theStandardFolderList()
class has to be implemented. The first one allows to fully control how the list items should look like, the second one is a lot simpler but does not give full control over the layout.- Target Classes
- Implementing one or more
TargetData()
classes defines, how TbSync can access the local elements like address books, calendars or whatever is used to store the elements received from the server.
Base Class¶
-
class
Base
()¶ Base class for the TbSync provider interface.
-
Base.
abAutoComplete
(accountData, query)¶ Implement this method, if this provider should add additional entries to the autocomplete list while typing something into the address field of the message composer.
The return value is an Array of Objects and each Object needs the following attributes:
value
: An email address written likeDisplayName <EmailAddress>
.comment
:Optional
A comment displayed to the right of the value in the autocomplete list.icon
:Optional
A chrome uri to a 16x16 icon.style
:Optional
A CSS class name.
When creating directories, you can set:
directory.setBoolValue("enable_autocomplete", false);
to disable the default autocomplete for this directory and have full control over the autocomplete.
Arguments: - accountData (AccountData) – The AccountData instance of the account being queried.
- query (string) – The search query.
Returns: Array of Objects.
-
Base.
getApiVersion
()¶ Returns the version identifier of the TbSync API this provider is using. If it is not matching the version identifier of the TbSync add-on the user has currently installed, this provider add-on is not loaded.
Returns: string – The API version identifier.
-
Base.
getConnectionTimeout
(accountData)¶ Returns the connection timeout for an active server request, so TbSync can append a countdown to the connection timeout, while waiting for an answer from the server. Only syncstates which start with
send.
will trigger this, seeSyncData.setSyncState()
.Arguments: - accountData (AccountData) – The AccountData instance for the account for which the timeout is being requested.
Returns: integer – The timeout in milliseconds.
-
Base.
getCreateAccountWindowUrl
()¶ Returns URL of the new account window.
The URL will be opened via openDialog(), when the user wants to create a new account of this provider.
Returns: string – Chrome uri to file to be used in create account dialog.
-
Base.
getDefaultAccountEntries
()¶ Returns an Object which contains all possible account properties of accounts of this provider, with its default value if not yet stored in the database.
The returned Object uses the properties names as key and its default values as their value:
return { "username" : "", "host" : "", "https" : true, "someOtherOption" : false, }
Please also check the standard account properties added by TbSync.
defaults.provider = provider; defaults.accountID = ""; defaults.lastsynctime = 0; defaults.status = "disabled"; defaults.autosync = 0; defaults.accountname = "";
Returns: Object – List of properties with default values.
-
Base.
getDefaultFolderEntries
()¶ Returns an Object which contains all possible folder properties of folders of this provider, with its default value if not yet stored in the database.
The returned Object uses the properties names as key and its default values as their value:
return { "someSetting" : "none", }
Please also check the standard folder properties added by TbSync:
defaults.accountID = accountID; defaults.targetType = ""; defaults.cached = false; defaults.selected = false; defaults.lastsynctime = 0; defaults.status = ""; defaults.foldername = ""; defaults.downloadonly = false;
Returns: Object – List of properties with default values.
-
Base.
getEditAccountOverlayUrl
()¶ Returns uri to the overlay for the edit account dialog (chrome://tbsync/content/manager/editAccount.xul)
The overlay must (!) implement:
tbSyncEditAccountOverlay.onload(window, accountData)
which is called each time an account of this provider is viewed/selected in the manager and gets passed the AccountData of the corresponding account.
Returns: string – Chrome uri to overlay for edit account dialog.
-
Base.
getMaintainerEmail
()¶ Returns the email address of the maintainer (used for bug reports).
Returns: string – An email address.
-
Base.
getProviderIcon
(size, accountData=null)¶ Returns location of a provider icon.
Arguments: - size (integer) – Size of the requested icon.
- accountData (AccountData) – The AccountData instance of the account, which is requesting the icon. Optional.
-
Base.
getProviderName
()¶ Returns name of this provider for the Add account menu of tbe TbSync account manager.
Returns: string – A name.
-
Base.
getSortedFolders
(accountData)¶ Returns all folders of the account, sorted in the desired order.
The order will be used in the folder list and also as the order to sync the resources of the account identified by the passed AccountData.
Arguments: - accountData (AccountData) – The AccountData instance for the account for which the sorted list of folders should be returned.
Returns: Array of
FolderData()
instances in the desired order.
-
Base.
getSponsors
()¶ Returns a list of sponsors, they will be sorted by sortIndex.
return { "sortIndex" : {name : "Name", description: "Something", icon: chrome://path/or/empty, link: "url://or/empty" }, }
Returns: Object – List of sponsors.
-
Base.
getStringBundleUrl
()¶ Returns the URL of the string bundle file of this provider, it can be accessed by
getString()
.Returns: string – Chrome uri to the string bundle file.
-
Base.
load
()¶ Called during load of this provider add-on.
-
Base.
onDisableAccount
(accountData)¶ Is called everytime an account of this provider is disabled in the manager UI.
Arguments: - accountData (AccountData) – The AccountData instance of the account being disabled.
-
Base.
onEnableAccount
(accountData)¶ Is called everytime an account of this provider is enabled in the manager UI.
Arguments: - accountData (AccountData) – The AccountData instance of the account being enabled.
-
Base.
syncFolder
(syncData, syncJob, syncRunNr)¶ Is called to synchronize a folder.
Never call this method directly, but use
AccountData.sync()
orFolderData.sync()
.Arguments: - syncData (SyncData) – The SyncData instance with information regarding the requested sync
- syncJob (string) – A specific sync job, defaults to “sync”, but can be set via the syncDescription. (see AccountData.sync or FolderData.sync).
- syncRunNr (integer) – Indicates the n-th number the account is being (re-)synced due to enforced retries. It starts with 1 and is limited by syncDescription.maxAccountReruns.
Returns: A
StatusData()
instance with information of the sync (failed/success).
-
Base.
syncFolderList
(syncData, syncJob, syncRunNr)¶ Is called to synchronize the folder list.
Never call this method directly, but use
AccountData.sync()
.Arguments: - syncData (SyncData) – The SyncData instance with information regarding the requested sync
- syncJob (string) – A specific sync job, defaults to “sync”, but can be set via the syncDescription. (see AccountData.sync or FolderData.sync).
- syncRunNr (integer) – Indicates the n-th number the account is being (re-)synced due to enforced retries. It starts with 1 and is limited by syncDescription.maxAccountReruns.
Returns: A
StatusData()
instance with information of the sync (failed/success).
-
Base.
unload
()¶ Called during unload of this provider add-on.
-
FolderList Classes¶
The DOM of the folderlist can be accessed by its ID and the FolderData of each entry is attached to its row. To get the FolderData of the selected row can be accessed like so:
let folderlist = document.getElementById("tbsync.accountsettings.folderlist");
let folderData = folderList.selectedItem.folderData;
-
class
StandardFolderList
()¶ StandardFolderList class.
-
StandardFolderList.
getAttributesRoAcl
(folderData)¶ Returns the attributes for the readonly menuitem element of the ACL selector for a folder to be shown in the folderlist. You can define any available attribute (label, disabled, hidden, style, …) by returning an Object which uses the attribute names as key and its values as their value. For example:
return { label: "Readonly access", disabled: false }
If both (RO+RW) do not return any attributes, the ACL menu is not displayed at all.
Arguments: - folderData (FolderData) – The FolderData instance of the folder for which the attributes for the ACL RO XUL element are requested.
Returns: Object – A list of attributes and their values for the ACL RO XUL element.
-
StandardFolderList.
getAttributesRwAcl
(folderData)¶ Returns the attributes for the read/write menuitem element of the ACL selector for a folder to be shown in the folderlist. You can define any available attribute (label, disabled, hidden, style, …) by returning an Object which uses the attribute names as key and its values as their value. For example:
return { label: "Read/Write access", disabled: true }
If both (RO+RW) do not return any attributes, the ACL menu is not displayed at all.
Arguments: - folderData (FolderData) – The FolderData instance of the folder for which the attributes for the ACL RW XUL element are requested.
Returns: Object – A list of attributes and their values for the ACL RW XUL element.
-
StandardFolderList.
getFolderDisplayName
(folderData)¶ Returns the display name for a folder to be shown in the folderlist.
Arguments: - folderData (FolderData) – The FolderData instance of the folder for which the display name is requested.
Returns: string – Display name of the folder.
-
StandardFolderList.
getTypeImage
(folderData)¶ Returns the icon for a folder to be shown in the folderlist.
Arguments: - folderData (FolderData) – The FolderData instance of the folder for which the icon is requested.
Returns: string – Chrome URL of icon.
-
StandardFolderList.
onContextMenuShowing
(window, folderData)¶ Is called before the context menu of the folderlist is shown, allows to show/hide custom menu options based on the selected folder. During an active synchronisation, folderData will be null and the folder list will be disabled.
Arguments: - window (nsIDOMWindow) – Object of the account settings window.
- folderData (FolderData) – The FolderData instance of the selected folder.
-
-
class
FolderList
(provider)¶ Functions used by the folderlist in the main account settings tab
Arguments: - provider (string) – Identifier for the provider this FolderListView is created for.
-
FolderList.
getHeader
()¶ Returns an array of attribute objects, which define the number of columns and the look of the header
-
FolderList.
getRow
(document, folderData)¶ Is called to add a row to the folderlist. After this call, updateRow is called as well.
Arguments: - document – [in] document object of the account settings window
- folderData – [in] FolderData of the folder in the row
-
FolderList.
onContextMenuShowing
(document, folderData)¶ Is called before the context menu of the folderlist is shown, allows to show/hide custom menu options based on selected folder
Arguments: - document – [in] document object of the account settings window - element.ownerDocument - menuentry?
- folderData – [in] FolderData of the selected folder
-
FolderList.
toggleFolder
(event)¶ ToggleFolder event
-
FolderList.
updateReadOnly
(event)¶ updateReadOnly event
-
FolderList.
updateRow
(document, listItem, folderData)¶ Is called to update a row of the folderlist (the first cell is a select checkbox inserted by TbSync)
Arguments: - document – [in] document object of the account settings window
- listItem – [in] the listitem of the row, which needs to be updated
- folderData – [in] FolderData for that row
Target Classes¶
TbSync can manage different types of storage targets (calendars, address books, whatever) for
each folder / resource found on the server. The provider only has to set a value for the
targetType
folder property when creating new folders. For each possible value, the provider
must implememt a matching class of type TargetData in his provider namespace.
Example:
If one of the possible values of the targetType
property is MyCalendar
, the provider
must implement a TargetData class inside his provider.js
with a name of
TargetData_MyCalendar
.
When interacting with TbSync, for example when syncing a specific folder / resource,
you will usually have access to a FolderData()
instance, which will return the
associated TargetData via FolderData.targetData()
.
-
class
TargetData
(folderData)¶ TargetData constrcutor.
Arguments: - folderData (FolderData) – The FolderData instance of the folder for which this TargetData instance is being created.
-
TargetData.
disconnectTarget
()¶ Disconnects the target in the local storage from this TargetData, but does not delete it, so it becomes a stale “left over”. A call to
TargetData.hasTarget()
should returnfalse
, after this has been executed.
-
TargetData.
getTarget
()¶ Returns the actual target object (for example a nsIAbDirectory). If the target does not exist, it should be created.
Note
The thrown error message will be used as a status and TbSync will use
status.<Error.message>
from your string bundle (seeBase.getStringBundleUrl()
) for the actual error/status message.Throws: Error – Reason, why the target could not be created. Returns: Object – Whatever you want to use as target object for this TargetData.
-
TargetData.
hasTarget
()¶ Check, if the target object of this TargetData exists in the local storage.
Returns: boolean – True, if target exists.
-
TargetData.
removeTarget
()¶ Removes the target from the local storage. If it does not exist, return silently. A call to
TargetData.hasTarget()
should returnfalse
, after this has been executed.
-
TargetData.
setReadOnly
(value)¶ The readonly property of the associated folder has been changed via the TbSync UI.
Note
This might be changed to a general FolderProperty observer.
Arguments: - value (boolean) – The current value of the
downloadonly
folder property.
- value (boolean) – The current value of the
-
TargetData.
targetName
¶ Getter/Setter for the target name.
TbSync Class Reference¶
daskjd akdj askldja sdjka dasljd aldja dlja sdasldj adljkas dlasjkd alsd asldja sdlasjd aldj
AccountData¶
-
class
AccountData
(accountID)¶ AccountData
-
AccountData.
eventLogInfo
¶ Getter for an
EventLogInfo()
instance with all the information regarding this AccountData instance.
-
AccountData.
sync
(syncDescription)¶ Initiate a sync of this entire account by calling
Base.syncFolderList()
. If that succeeded,Base.syncFolder()
will be called for each available folder / resource found on the server.Arguments: - syncDescription (Object) –
Optional
- syncDescription (Object) –
-
EventLogInfo¶
-
class
EventLogInfo
(provider, accountname, accountID, foldername)¶ An EventLogInfo instance is used when adding entries to the TbSync Event Log. The information given here will be added as a header to the actual event.
Arguments: - provider (string) –
Optional
A provider ID (also used as provider namespace). - accountname (string) –
Optional
An account name. Can be arbitrary but should match the accountID (if provided). - accountID (string) –
Optional
An account ID. Used to filter events for a given account. - foldername (string) –
Optional
A folder name.
-
EventLogInfo.
accountID
¶ Getter/Setter for the account name of this EventLogInfo.
-
EventLogInfo.
accountname
¶ Getter/Setter for the account ID of this EventLogInfo.
-
EventLogInfo.
foldername
¶ Getter/Setter for the folder name of this EventLogInfo.
-
EventLogInfo.
provider
¶ Getter/Setter for the provider ID of this EventLogInfo.
- provider (string) –
FolderData¶
-
class
FolderData
(accountData, folderID)¶ FolderData
-
FolderData.
eventLogInfo
¶ Getter for an
EventLogInfo()
instance with all the information regarding this FolderData instance.
-
FolderData.
sync
(syncDescription)¶ Initiate a sync of this folder only by calling
Base.syncFolderList()
and thanBase.syncFolder()
for this folder / resource only.Arguments: - syncDescription (Object) –
Optional
- syncDescription (Object) –
-
FolderData.
targetData
¶ Getter for the
TargetData()
instance associated with this FolderData. See Target Classes for more details.
-
ProgressData¶
-
class
ProgressData
()¶ ProgressData to manage a
done
and atodo
counter.Each
SyncData()
instance has an associated ProgressData instance. SeeSyncData.progressData()
. The information of that ProgressData instance is used, when the current syncstate is prefixed bysend.
,eval.
orprepare.
. SeeSyncData.setSyncState()
.-
ProgressData.
done
¶ Getter for the
done
counter.
-
ProgressData.
inc
(value=1)¶ Increment the
done
counter.Arguments: - value (integer) –
Optional
Set incrementation value.
- value (integer) –
-
ProgressData.
reset
(done=0, todo=0)¶ Reset
done
andtodo
counter.Arguments: - done (integer) –
Optional
Set a value for thedone
counter. - todo (integer) –
Optional
Set a value for thetodo
counter.
- done (integer) –
-
ProgressData.
todo
¶ Getter for the
todo
counter.
-
ProviderData¶
-
class
ProviderData
(folderData)¶ ProviderData
Constructor
Arguments: - folderData (FolderData) – FolderData of the folder for which the display name is requested.
-
ProviderData.
eventLogInfo
¶ Getter for an
EventLogInfo()
instance with all the information regarding this ProviderData instance.
StatusData¶
-
class
StatusData
(type=success, message, details)¶ A StatusData instance must be used as return value by
Base.syncFolderList()
andBase.syncFolder()
.StatusData also defines the possible StatusDataTypes used by the TbSync Event Log.
Arguments: - type (StatusDataType) – Status type (see const definitions below)
- message (string) –
Optional
A message, which will be used as sync status. If this is not a success, it will be used also in the TbSync Event Log as well. - details (string) –
Optional
If this is not a success, it will be used as description in the TbSync Event Log.
-
StatusData.
ACCOUNT_RERUN
¶ Sync of the entire account will be aborted and restarted completely.
-
StatusData.
ERROR
¶ Sync of the entire account will be aborted.
-
StatusData.
FOLDER_RERUN
¶ Sync of the current folder/resource will be restarted.
-
StatusData.
INFO
¶ Successfull sync, but message and details provided will be added to the event log.
-
StatusData.
SUCCESS
¶ Successfull sync.
-
StatusData.
WARNING
¶ Sync of this resource will be aborted and continued with next resource.
Example usage:
let status = TbSync.StatusData.INFO;
return new TbSync.StatusData(status, "Have a nice day!", "Everything is fine.");
SyncData¶
-
class
SyncData
(accountID)¶ There is only one SyncData instance per account which contains all relevant information regarding an ongoing sync.
-
SyncData.
accountData
¶ Getter for the
AccountData()
instance of the account being currently synced.
-
SyncData.
currentFolderData
¶ Getter for the
FolderData()
instance of the folder being currently synced. Can benull
if no folder is being synced.
-
SyncData.
eventLogInfo
¶ Getter for an
EventLogInfo()
instance with all the information regarding this SyncData instance.
-
SyncData.
getSyncState
()¶ Gets the current syncstate and its timestamp of the ongoing sync. The returned Object has the following attributes:
state
: the current syncstatetimestamp
: its timestamp
Returns: Object – The syncstate and its timestamp.
-
SyncData.
progressData
¶ Getter for the
ProgressData()
instance of the ongoing sync.
-
SyncData.
setSyncState
(state)¶ Sets the syncstate of the ongoing sync, to provide feedback to the user. The selected state can trigger special UI features, if it starts with one of the following prefixes:
send.
,eval.
,prepare.
: The status message in the UI will be appended with the current progress stored in theProgressData()
associated with this SyncData instance. SeeSyncData.progressData()
.send.
: The status message in the UI will be appended by a timeout countdown with the timeout being defined byBase.getConnectionTimeout()
.
Arguments: - state (string) – A short syncstate identifier. The actual message to be displayed in the UI will be looked up in the string bundle of the provider associated with this SyncData instance (
Base.getStringBundleUrl()
) by looking forsyncstate.<state>
. The lookup is done viagetString()
, so the same fallback rules apply.
-
TbSync Methods Reference¶
daskjd akdj askldja sdjka dasljd aldja dlja sdasldj adljkas dlasjkd alsd asldja sdlasjd aldj
getString()¶
-
getString
(key, provider)¶ Get a localized string from a string bundle.
TODO: Explain placeholder and :: notation.
Arguments: - key (string) – The key to look up in the string bundle
- provider (string) –
Optional
The provider whose string bundle should be used to lookup the key. SeeBase.getStringBundleUrl()
.
Returns: string – The entry in the string bundle of the specified provider matching the provided key. If that key is not found in the string bundle of the specified provider or if no provider has been specified, the string bundle of TbSync itself we be used as fallback. If the key could not be found there as well, the key itself is returned.
TbSync Event Log¶
The TbSync event log can be used by any provider to log messages which could be important for the user.
-
eventlog.
add
(type, eventInfo, message, details)¶ Adds an entry to the TbSync event log
Arguments: - type (StatusDataType) – One of the types defined in
StatusData()
- eventInfo (EventLogInfo) – EventLogInfo for this event.
- message (string) – The event message.
- details (string) –
Optional
The event details.
- type (StatusDataType) – One of the types defined in
Example usage:
let eventInfo = new TbSync.EventLogInfo();
TbSync.eventlog.add(TbSync.StatusData.WARNING, eventInfo, "Something bad happend!");
Instead of creating a custom EventLogInfo()
instance, you can also get one with prefilled information via