Greetings,

On Friday, 2022-03-18 11:50:33 +0100, I myself wrote:

> Nikos,
> 
> On Thursday, 2022-03-17 19:04:04 +0200, you wrote:
> 
> > ...
> > http://mmogilvi.users.sourceforge.net/software/oauthbearer.html
> > ...
> 
> Really interesting reading.  Thanks for the pointer.  And also thanks to
> the other responders.

Matthew Ogilvie's write-up at the above URL was not only interesting but
also extremely helpful.  It basically covers four points:

1. Background information on OAuth 2.

2. A how-to about setting up one's Google mail account for OAuth 2 and a
   Python script (requiring a small configuration file),  which gets you
   your first two OAuth tokens: an "access token" which has to be passed
   to Google as a password,  but which has only a life time of 60 minut-
   es, and a "refresh token" which is valid until you change your Google
   password or maybe also  until Google decides  enough being enough and
   starts rejecting your refresh requests with  "HTTP Error 400: Bad Re-
   quest" messages  which you'll find at the bottom of the Python trace-
   back from  Matthew's script.   As long as the  refresh token is valid
   you will have to use this script on a rather regular basis to get new
   valid access tokens.

3. Gentoo-ready patches for "net-mail/fetchmail"  up to at least version
   6.4.13 which however will only support IMAP and will not work in dae-
   mon mode, thus requiring a "cron" job for fetching mail.

   Matthew also points out  that Gentoo offers a still masked "net-mail/
   fetchmail" version 7.0.0_alpha9-r1  which supports OAuth 2, POP3, and
   daemon mode.

4. A description how to tweak "mail-mta/postfix" so it supports OAuth 2.
   This involves installing a "cyrus-sasl-xoauth2" plugin  not available
   in the Gentoo repository,  a complex configuration setup  for a full-
   fledged MTA which above all is dynamically changing (at least, if you
   want to handle outgoing mail for more than one user),  special "sudo-
   ers" rules for these mailing users,  and "cron" jobs  to periodically
   send their mail off to their Google accounts.

Following part 2 of this guide I soon had my Google account OAuth-ready.
The Python script from Matthew requires a configuration file the path to
which has to be  explicitly specified  in every call.   My configuration
file resides at "~/.../oauth.cfg" and contains:

client_id=...
client_secret=...
access_token_file=/home/rainer/.../oauth-access-token
refresh_token_file=/home/rainer/.../oauth-refresh-token
max_age_sec=1800

The first two lines  specify the Google project  just created,  the next
two lines define  the absolute paths  to the two token files to be used,
and the last line sets the access token age  before which the token will
not be renewed.  DO NOT try to add empty or comment lines to this file!

Regarding the adaption of "fetchmail"  in part 3  I opted for installing
version 7.0.0_alpha9-r1,  since I was used to  POP3 and daemon mode [1].
Version 7 is still masked,  so to be able  to emerge it  execute (in the
first "echo" command replace "amd64" with YOUR architecture):

   # mkdir -p /etc/portage/package.accept_keywords
   # echo '>=net-mail/fetchmail-7.0.0_alpha9-r1 ~amd64' \
           >> /etc/portage/package.accept_keywords/Oauth
   # mkdir -p /etc/portage/package.unmask
   # echo '>=net-mail/fetchmail-7.0.0_alpha9-r1' \
           >> /etc/portage/package.unmask/OAuth

[1] If you do not like  installing an  alpha-version,  want to use POP3,
    but do not insist on daemon mode, I've meanwhile found out that Gen-
    too also provides a package "net-mail/mpop"  from the same author as
    the MTA I decided to install instead of "mail-mta/postfix".   Howev-
    er,  Gentoo-wise this package is almost two years behind  due to the
    lack of a Gentoo maintainer, so you might want to install it direct-
    ly from

       https://marlam.de/mpop/

Of course the new "fetchmail" version  also introduced new configuration
items.  Here is my new "~/.fetchmailrc" file (the "authenticate" direct-
ive as well as the last three lines are new):

set    daemon 60
set    invisible
set no syslog

poll          pop.gmail.com
protocol      POP3
service       995
authenticate  oauthbearer

username      "rainer.woi...@gmail.com"
dropdelivered
fetchall
no keep
mda           "/usr/bin/procmail -pf %F"
passwordfile  "/home/rainer/.../oauth-access-token"
sslmode       wrapped
sslcertck

Even though I run  "fetchmail" in daemon mode,  it's not running all the
time.  It's started once when I log in, but my backup script which I use
at least once a day will again terminate it  before doing anything else,
so my mailbox will never change  between my last backup  and hibernating
my laptop.

And yes,  I almost never shutdown my laptop,  but rather suspend or hib-
ernate it.  Thus I'll possibly need a fresh access token when I manually
start "fetchmail",  but it's not necessary  to repeatedly  update it via
"cron" while "fetchmail" isn't running at all.   The same holds when re-
suming from suspension or hibernation:  only when "fetchmail" is running
the age of the access token should be checked  and potentially a new one
requested.

So I'll have to use Matthew's "oauth.py" script in three ways:

1. Running it the first time or starting over to get both, a new refresh
   token and a new access token.

2. Unconditionally checking  the age of the access token  and optionally
   requesting a new one, regardless of whether or not "fetchmail" is ex-
   ecuting.

3. Only checking the age of the access token and optionally requesting a
   new one, if "fetchmail" is really executing.

This leads to wrapper script "~/.../oauth.sh" which knows the options it
has to pass to script "oauth.py":

#! /bin/bash -u
#
# Script to retrieve new OAuth tokens from Google mail.
#
# There are two types of OAuth tokens,  an "access token" which only has
# a life time of 60 minutes and is required for both, fetching mail from
# and sending mail via Google mail, and a "refresh token" which is valid
# until changing  one's Google mail password  or until Google decides it
# has been used long enough,  and is required  to get a new "access tok-
# en".
#
# The action performed by this script depends on its first argument:
#
# "init":   Get a (new) refresh token  together with a new access token.
#           This causes an URL to be sent to standard output,  which you
#           have to point your browser to.   At Google's mail login page
#           use your mail address and password to log into your mail ac-
#           count, agree to accessing your project, copy the authorizat-
#           ion code then provided,  paste it after the text "Enter ver-
#           ification code:" in the terminal window where this script is
#           still running, and hit Enter.
#
# "update": Update the access token,  except when it is younger than the
#           maximum age specified in configuration file "oauth.cfg".
#
# no arg:   Only when "fetchmail" is running  update the access token as
#           if "update" has been specified.

dir=$(dirname $(realpath "$0"))   # Symlink-free abs path to script dir.
cfg="--config_file=$dir/oauth.cfg"          # Configuration file option.

if [[ "${1-}" = init ]]
then "$dir/oauth.py" "$cfg" --obtain_refresh_token_file
elif pgrep -u $USER fetchmail > /dev/null || [[ "${1-}" = update ]]
then "$dir/oauth.py" "$cfg" --auto_refresh
fi

Now keeping the above comment regarding "init" in mind I executed:

   $ ~/.../oauth.sh init

to get my first OAuth 2 access tokens.  I then created:

1. A new "fetchmail" alias (which will also be run upon login):

   $ alias fetchmail='~/.../oauth.sh update ; fetchmail'

2. A "crontab" entry for my own userid  (don't forget to add yourself to
   group "cron"):

# When "fetchmail" is started, it will request a new "OAuth" access tok-
# en from Google as soon as the current token  is older than 30 minutes.
# And as long as "fetchmail" is running,  this "cron" job, too, will re-
# new the "OAuth" access token when it is older than 30 minutes.   Since
# we start this "cron" job three times an hour, this will result in acc-
# ess tokens (except for the first one, which will be refreshed after 30
# to 50 minutes) being refreshed every 40 minutes.   This fits well with
# the maximum life time of 60 minutes for any access token.

11,31,51 * * * * $HOME/.../oauth.sh

3. The hook script  "/lib64/elogind/system-sleep/oauth-token.sh" for the
   "elogind" service:

#! /bin/bash -u
#
# When resuming from hibernation or suspension update Google's OAuth to-
# ken for user "rainer".
#
# This script will be called by "elogind" with exactly two arguments:
#
# $1: Either "pre" or "post".
# $2: Either "hibernate", "hybrid-sleep",  "suspend",  or "suspend-then-
#     hibernate".
#
# The "sleep" command is required  to give the host some time connecting
# the WiFi before running "oauth.sh",  and taking this nap  in the back-
# ground prevents it from delaying "elogind" while firing up the WiFi:

[[ "$1" = pre ]] || (sleep 10 ; sudo -u rainer ~rainer/.../oauth.sh) &

Now it's time to just start "fetchmail"  via its new alias  and to catch
up with one's incoming mail ...

However,  I did not follow Matthew's suggestions in part 4 regarding the
configuration of "mail-mta/postfix" because the configuration effort for
a full-fledged, system wide MTA  as well as adding another "ebuild" file
to my local overlay  seemed like overkill to me.   Up to now I was using
"ssmtp" for sending mail,  and if I remember correctly, the first "s" in
this name  was referring to "simple".   Its configuration file just con-
tained eight lines.   Looking around I found  Gentoo package  "mail-mta/
msmtp",  which supports OAuth 2 and also a user local configuration file
at "~/.msmtprc".  Here are the relevant lines from mine:

# Name the only account defined here "default", so it overrides the def-
# ault account defined in file "/etc/msmtprc":

account                default

auth                   oauthbearer
domain                 gmail.com
host                   smtp.gmail.com
passwordeval           cat ~/.../oauth-access-token
port                   587
protocol               smtp
tls                    on
tls_certcheck          on
tls_starttls           on
user                   rainer.woi...@gmail.com

Now the only thing left to do  is telling one's MUA not to pipe outgoing
mail directly to the standard "/usr/sbin/sendmail", but rather to script
"~/.../msmtp.sh" instead,  so we can refresh the OAuth access token,  if
necessary, before really sending off the mail.   Script "~/.../msmtp.sh"
contains:

#! /usr/bin/bash -u
#
# Before sending the mail  refresh the access token,  if necessary,  and
# since the mail to be sent is provided on standard input,  route stand-
# ard input around the call to "oauth.sh":

{ cat >&3 ; ~/.../oauth.sh update ; } 3>&1 | msmtp "$@"

Should you MUA  not provide a way for specifying  the programme to which
outgoing mail is piped,  you can simply modify  the symbolic link "/usr/
sbin/sendmail"  (which has just been set  by package "mail-mta/msmtp" to
point to "../bin/msmtp"):

   # cd /usr/sbin
   # rm sendmail
   # ln -s ~rainer/.../msmtp.sh sendmail

That's all, happy mailing ... :-)

Sincerely,
  Rainer

PS: This mail was sent to you  using "mail-mta/msmtp" set-up the way de-
    scribed above ... :-)

Reply via email to