Email OAuth2 Proxy

Microsoft Screws Their Users… Again…

 

Desktop Outlook Banned From Outlook.com and Hotmail.com POP3

Microsoft had stopped allowing users of their premium Outlook desktop product (versus the useless, neutered “Outlook” wannabe bloatware “Outlook for Windows” included force installed in Windows 11) to access their “free” @hotmail.com and @outlook.com emails via POP3 and SMTP (secured or not), forcing everyone to use effectively use IMAP mode (links here and here, backup here).

Leaving discussions over any reasons (e.g. financial greed trying to force clueless desktop Outlook + “free” MS email-using people to pay for more storage) and the sheer stupidity of forcing this down Outlook users’ throats (against, say, everyone else like those using Thunderbird or other third-party email clients) aside, I had simply left this aside, relying on my trusty K-9 Mail on Android to access any emails on these “throw-away” accounts…

Unfortunately, there were a few emails (mainly shopping-related receipts) that I wanted to keep – so once again, I had to roll-up my sleeves and fix shit Microsoft breaks get things working…

Google search basically found me Email OAUTH2 Proxy nearly immediately… Attempts at simply using the Docker image did not go so smoothly, so I ended up using pipx and did a “bare metal” install..

 

Trying To Understand/Explain Things

Furthermore, I found the author’s README.md hard to understand, so I decided to whip up my “own” documentation, based more around an intended outcome (that may require multiple switches/options used together), than say, explaining individual switches.

Since some explanation sections covers multiple points, I have used separate multiple sub-section headers denoting what/which point/s a singular section would resolve/be relevant to/answer.

 

OAUTH2 Client_ID and Microsoft

For the “free” @outlook.com and @hotmail.com services (it’s never free – you pay with your information), the bastards people at Microsoft have disabled the use of custom clients (unless you jump through a lot of hoops and/or pay a lot of money). Therefore, this configuration uses Thunderbird’s public client_id (i.e. the proxy is identifying itself, during OAUTH2 token generation, that it is “a Thunderbird email client”).

 

Headless Mode

This configuration runs “headless” (i.e. --no-gui) and as a background service (i.e. no manual input interaction) with all console output pushed to a log file. There are considerations to be aware of due to the latter point – refer to the section “New Accounts and OAUTH2 Token Generation“.

Refer to * footnote.

 

Single Domain Configuration

Wildcard Mode

Adding Users Semi-Automatically

To prevent me from having to manually create and repeat configuration snippets for every account, and also minimise the ports count (i.e. one port per domain and service vs. one for each account and service), I configured emailproxy to use wildcards per domain (i.e. allow_catch_all_accounts), allowing me to configure each server type (and service port) once, where any attempts to log in with a here-to-fore unknown email address (on said domain) or unknown password (refer to ‘How EmailProxy Determines An Account as “New”‘) would trigger the OAUTH2 token generation ceremony.

Refer to * footnote.

 

New Accounts and OAUTH2 Token Generation

Disabling “ANY” User Creation

Any manual actions required of the OAUTH2 token generation ceremony (like copying the temporary authentication URL for actual browser-based authentication then “pasting” the token as input) has to be done only in interactive mode (i.e. run the email-oauth2-proxy-manual.sh script). By virtue of this point, not just anyone, because of your use of “wildcard” domain, can use/abuse your proxy.

  • stop  the service
    • systemctl stop emailoauth2proxy
  • run the script interactively in the foreground
    • /opt/emailproxy/email-oauth2-proxy-manual.sh
  • run the email client with the “new” account, using a complex password (that has to be re-used for this account henceforth)
    • copy the authentication URL and access using standard browser with no existing logged in sessions for said OAUTH2 domain (e.g. use “incognito mode”)
    • run through the authentication process
      • it will end in a redirect to “http://localhost:8080” with a 404 – this is expected
      • copy the entire URL and paste it back (as input) to the running emailproxy process (which will be waiting for the input on the console)
    • force a check again (e.g. using Outlook’s “Send/Receive Groups” pull-down and selecting the correct Hotmail.com/Outlook.com account to “pull” the “Inbox”)
  • stop (CTRL-C) the emailproxy process/thread and (re)start the service
    • systemctl start emailoauth2proxy

* Because of the out-of-band authentication and no HTTP interface of emailproxy, the process can only be, at best, semi-automated. i.e. You will need to execute any new OAUTH2 token generation process from the server directly.

 

Disabling Auto Force New Token Generation

Separating Credentials Best Practice

Enforcing “Basic/Simple” Authentication

How EmailProxy Determines An Account Is “New”

Since --cache-store specifies a separate file, any actual accounts’ tokens and other (copied) settings (from the “wildcard” source service) will be stored in said separate file, encrypted by the initial password used during OAUTH2 token generation.

I consider this “best practice” as I only need to review said file for changes.

By default (i.e. “delete_account_token_on_password_error = True“), emailproxy assumes any failure to decrypt any existing data (or finds missing data) from individual account sections means (re-)triggering a new OAUTH2 token generation ceremony/process.

By using “delete_account_token_on_password_error = False“, any failure in decrypting encrypted data of the account would not (re-)trigger a new OAUTH2 token generation ceremony/process.

Although if missing data, or if the account section was completely missing (i.e. new), the OAUTH2 token generation ceremony/process would still be triggered (and correctly so).

This acts as a sort of “basic/simple” security check – not anyone can just attempt to use your generated token and get access to your email – only when attempting to authenticate with the same password used during the initial OAUTH2 token generation ceremony/process will the client be successful.

 

Continue reading

x11vnc Copy-and-Paste…

To prevent typos and OS line break-type kerfuffles, I typically copy files instead of copy-pasting any files’ contents across VNC sessions.

Somehow, I came across wanting to just copy-paste a file via a VNC session, which used to work ye long ago… But it just was not happening…

Diving into the ‘net for answers, I came across autocutsel… Although some places stated to use xstartup files, as I was using x11vnc, this was not possible, so I simply ended up creating a services file (with a dependency on the x11vnc service):

Continue reading

CPanel Email Filters

As part of managing my own web presence, including a hosted email server with limited users (both in numbers and geography), I tend to try and cut large swathes of spam by simply “binning” any emails that have any association with specific TLDs, like .ru or .us or .cn– whereby I know that my users and I have no legitimate reason to receive any email coming from those TLDs or passing through servers using any such TLDs.

However, it came to pass that some ham were getting caught, but simply looking at the email headers was not helping. Using CPanel’s in-built testing tool was helpful in surfacing which of my rules was triggering the spam trap, but not exactly why (or what part of the email was triggering it).

The triggering rule looked like regex, so I immediately tried to hunt down converted/parsed file to try and copy the rule in converted regular expression form.

Attempting to poke at the ~/.cpanel/filter.yaml and ~/.cpanel/filter.cache and even the /etc/vfilters/<domain> did not turn up the regular expressions I was looking for.

In desperation, I took a quick look at the CPanel test tool results and decided to just copy the regex shown outright…

Unfortunately, pasting that regex directly into a regex test tool did not work…

Continue reading

GNU getopt Needs A Helper

So, recently at work, I found myself knee deep in… scripts…

Most of my scripts had ugly positional parameters/arguments (you know, $1 was the value for this, $2 was the input for that)… So, I dug up getopt… But then I quickly spiralled down the time-sucking rabbit hole of trying to automate some other bits, like being able to print the “usage” by “simply” plucking out all the options given to getopt in the first place…

Continue reading

sed Shennanigans…

Escaping…

For anyone familiar with regular expressions, the need to escape characters, that might otherwise be construed as some “special command”, is a regular affair…

sed posed a particular challenge for me when attempting to escape variables that are used as a replacement string. So, to cut the long story short, after 8 hours of trying, testing and re-testing, I finally got the solution…

In a bash shell, try the following:

TESTSTRING='\/12345678\90!@#$%^&*()-_=+{}[];:",.<>? `~abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
sed "s#\([^[:alnum:]]\)#\\\\\1#g"<<<$TEST

Otherwise, in a script, try the following:

TESTSTRING='\/12345678\90!@#$%^&*()-_=+{}[];:",.<>? `~abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
TESTSTRING=`echo $TESTSTRING|sed 's#\([^[:alnum:]]\)#\\\\\1#g'

WARNING: This does not work with intended backreferences (e.g. \1, \2, … \9, etc.) as the leading backslash will also be escaped (see the \9 in the tests above).

NOTE: The single-quote character was not part of the tests as I could not find a way to escape that as part of the variable assignment.