Skip to content

heinrich-ulbricht/teasm-companion

Repository files navigation

Teasm Companion

A companion app for Microsoft Teams to back up your chats. Pronounced "Teams Companion".

Created in lockdown times to counter code withdrawal. Playground for C# 9, Reactive Extensions, some Polly, LevelDB and more IMAP than expected.

What does it do?

Teasm Companion is like a special Teams client. It fetches your chats and chat messages (those you would normally see when clicking on the "Chat" icon in Microsoft Teams) and stores them locally.

Teasm Companion retrieves the following data for any of your authenticated Teams accounts:

  • Chat messages (not all at once, but over time)
  • Some chat metadata
  • Information about chat participants
  • Basic Tenant information

In essence its getting chat messages from chats and meetings you participated in and stores those messages in such a way that you can access and search them in an e-mail client of your choice (Thunderbird, Claws Mail, Outlook, ...).

Note: It can access no more data than you can access in the Teams client.

What's the use case?

Making sure that you have always access to your conversations. Those conversations often contain important information that must not be lost.

How does it work?

Teasm Companion can do everything Microsoft Teams can do and is dependent on Microsoft Teams running at the same time (Desktop app, Chrome or new Edge).

Teasm Companion uses existing access tokens from Teams to access the same APIs Teams uses. It borrows those tokens from a running Teams client. So some time after you authenticate in the Teams app or in a browser tab Teasm Companion will grab those tokens and do its work.

There is no authentication done by Teasm Companion. You authenticate in Teams. The Companion will ride along.

Why not build a "normal" Teams app?

Why not use Microsoft Graph and build an app for Microsoft Teams?

It's not feasible for a variety of reasons.

What are the prerequisites?

The following is needed to run Teasm Companion:

  • Windows 10 or Linux (tested on Fedora 33 & 34)
  • .NET 6.0
  • A local IMAP server, see section "You need an IMAP server" below for details
  • ldbdump.exe (or ldbdump on Linux) - which is included in this repo - must be present and executable, see TeamsTokenRetrieval/precompiled/README.md for details; you can build it yourself if you want, instructions are in the README

How are chat messages retrieved?

Chats are retrieved in roughly the same order as they are listed in Microsoft Teams. Most recent ones are retrieved first.

Initial Chat Retrieval

When you start Teasm Companion for the first time it retrieves a list of all your chats (without messages), just like Teams does.

This will only be done once. The data will be cached and further on only changed and new chats will be retrieved. Just like Teams does it.

Chat Retrieval Pace

Teasm Companion plays nice with the APIs by not requesting too many chat messages at once. Thus only chats from the past days are retrieved a bit "faster" and after that chats are retrieved more "slowly". (See the Configuration section on how to configure "fast" and "slow".)

Live Chat Notifications

Teasm Companion also subscribes to chat notifications (just like Teams does) and as soon as it receives a "new chat message" notification the message is stored right away as a kind of "draft". This draft is later updated when the whole chat is updated incrementally.

Incremental Chat Updates

Teasm Companion regularely checks for chats with new messages and gets only those messages. It retrieves the list of changed chats just like Teams does it and updates them, leaving old chats untouched.

You need an IMAP server

Why IMAP? Because chat messages map pretty well to e-mails. There's a sender, a list of recipients, a message, attachments and so on. (Apparently there is a whole chat client out there built on the basis of IMAP.)

And you get a proven user interface. Any e-mail client fits the purpose and allows to read, manage and search chat messages.

Since Teasm Companion needs the CONDSTORE IMAP capability to implement locking you have a reduced set of IMAP servers and services available with Dovecot being the most popular one. Have a look at the "IMAP extensions and server support" table to see all your options.

It's best to use a local Dovecot IMAP server as this is guaranteed to work well. There are plenty of Docker images out there giving you exactly that even on Windows. For example with docker-imap-devel you get a working and lightweight server set up in no time.

A remote server could also work but the code is absolutely not optimized for this use case. Also, be careful. Don't put your data at risk in places where it doesn't belong or can get lost.

What can be configured?

You don't really have to configure anything, except for the Imap* properties. All other properties have reasonable default values.

Rename config.template.json to config.json. Then, in config.json, you can configure the following:

Setting Data type Meaning Sample value
ImapHostName text Host name of the IMAP server "localhost"
ImapPort number IMAP port 10143
ImapUserName text User name for the IMAP account "user@localdomain.local"
ImapPassword text Password for the IMAP account "correct horse battery staple"
FastChatRetrievalDays number Number of days to perform "fast chat retrieval" for (used to quickly pull recent chats) 7
FastChatRetrievalWaitTimeMin number Maximum number of minutes to wait between retrieving chats in "fast retrieval mode" 1
SlowChatRetrievalWaitTimeMin number Maximum number of minutes to wait between retrieving chats in "slow retrieval mode" 30
UpdatedChatRetrievalWaitTimeSec number Number of seconds to wait after updating an existing chat 5
ResolveUnknownUserIdsJobIntervalMin number A job runs periodically to resolve unknown user IDs in already stored messages; this is its interval in minutes 10
TenantIdsToNotSubscribeForNotifications array of text IDs of tenants that should not be watched for notifications (use for inactive tenants) [ "00000000-0000-beef-0000-000000000000" ]
ChatIdIgnoreList array of text IDs of chats that should not be retrieved [ "19:something@unq.gbl.spaces" ]
DebugDisableEmailServerCertificateCheck boolean Ignore IMAP server certificate errors; use this for local IMAP servers or testing false
DebugClearLocalCacheOnStart boolean Clear the local cache on start; note: after application updates the cache is cleared automatically false
LogLevel text; one of "Debug" or "Information" How much information do you want to see in the console and log files? "Debug"

Those options are specific to login automation (which is entirely optional!):

Setting Data type Meaning Sample value
AutoLogin JSON list Tenants to automate the log in for see sample below
ChromeBinaryPath text Absolute path to chrome binary "/usr/bin/chromium-browser"
WebDriverDirPath text Absolute path to the directory where the web driver is located; note: driver and Chrome version must match otherwise the program will throw "/home/user/Portable"
MobileNumberForSignalMfaRelay text Mobile number for optional MFA relay via Signal Messenger "+4915701234567"

Sample value for the AutoLogin property which will try to log Megan into two tenants:

[
    {
      "AccountEmail": "megan.bowen@contoso.com",
      "TenantId": "c0bbfdb8-f4bf-458c-bed5-a7d832eb89f6",
      "DisplayName": "Contoso Inc"
    },
    {
      "AccountEmail": "megan.bowen@contoso.com",
      "TenantId": "c0bbfdb8-f4bf-458c-bed5-a7d832eb89f6",
      "DisplayName": "Adatum GmbH"
    }
]

Again, the IMAP configuration is the most important one.

Logging

Teasm Companion comes with extensive logging. It is fun watching the notifications flow into the console as you interact within Teams.

The default log level is "Debug" which shows nearly everything the application does. Logs are shown in the console window and are also stored in the "logs" sub-directory. Log files are automatically removed after a couple of days.

How do I run it?

Clone the repo. Build TeasmCompanion using Visual Studio, Visual Studio Code or the command line, depending on your platform and preference. Then create and configure a config.json and run TeasmCompanion.exe (Windows) or TeasmCompanion.dll (Linux).

Windows:

  • Open solution in Visual Studio
  • Build project TeasmCompanion
  • To run: start TeasmCompanion.exe

Linux:

  • Open a terminal, switch to the cloned repo directory
  • dotnet restore
  • dotnet build --no-restore
  • To run: dotnet TeasmCompanion/bin/Debug/net5.0/TeasmCompanion.dll

Troubleshooting

Teasm Companion cannot find a token for initial chat list retrieval

Tokens for initial chat retrieval have a lifetime of about an hour and need to be renewed afterwards. You can trigger renewal in your Teams client by switching to another tenant and back. You can also clear the cache of either the Teams client or your browser, then restart/reload the client. That should renew the token as well.

Note: The tokens needed to get the actual chat messages per chat have a a longer lifetime of >1 day, so once the chat list has been retrieved you can let it run unattended for some time. The Teams clients might even renew this token from time to time automatically.

Some e-mails seem empty - why?

Configure your e-mail client to always show or prioritize HTML content. Some e-mails might come with empty "text" content while having only their "HTML" content set.

Disclaimer

There is no warranty. Assess your risk and proceed accordingly. Everything might break at any time.

Further reading

To learn more go to the TeasmCompanion folder. The README there contains more details about how things are implemented.

About

Teasm Companion for Microsoft Teams - Back up your chats

Resources

License

Stars

Watchers

Forks

Languages