Postanowiłem przestać się męczyć środowiskiem graficznym i powrócić do źródeł. Moim pierwszym programem do poczty był Pine i o nim będzie mowa. A raczej o jego nowszym bracie: Alpine.
Instalacja i konfiguracja na macOS-ie jest prościutka. Będę ją rozbudowywał i dostosowywał w miarę używania. Na początek postanowiłem skończyć z bezpośrednim dostępem do skrzynek na serwerze. Alpine będzie czytał pocztę z lokalnych folderów, które z kolei będą synchronizowane w obie strony – między moim laptopem, a serwerem – za pomocą narzędzia: offlineimap.
Instalacja offlineimap
Zatem najpierw zainstaluję offlineimap-a za pomocą Homebrew:
brew install offlineimap
Konfiguracja kilku kont
Przykładowa konfiguracja dwóch kont (foo i bar) w .offlineimaprc:
[general]
accounts = foo,bar
# The pre-defined options are:
# Blinkenlights -- A fancy (terminal) interface
# TTYUI -- a text-based (terminal) interface
# Basic -- Noninteractive interface suitable for cron'ing
# Quiet -- Noninteractive interface, generates no output
# except for errors.
# MachineUI -- Interactive interface suitable for machine
ui = quiet
##### FOO ####################
[Account foo]
localrepository = Local_foo
remoterepository = Remote_foo
# Jak często sprawdzać pocztę (minuty)
autorefresh = 1
# Zrób 10 szybkich synchronizacji zanim zrobisz pełną
quick = 10
[Repository Local_foo]
type = Maildir
localfolders = ~/POCZTA/FOO
# kasuj na serwerze co skasuje lokalnie
sync_deletes = yes
[Repository Remote_foo]
type = IMAP
remotehost = mail.foo.pl
remoteuser = trompka@foo.pl
starttls = yes
sslcacertfile = /usr/local/etc/openssl/cert.pem
##### BAR ####################
[Account bar]
localrepository = Local_bar
remoterepository = Remote_bar
autorefresh = 1
quick = 10
[Repository Local_bar]
type = Maildir
localfolders = ~/POCZTA/BAR
sync_deletes = yes
[Repository Remote_bar]
type = IMAP
remotehost = mail.bar.com
remoteuser = trompka
starttls = yes
cert_fingerprint = 4375fcdalefh952z3b307f84350dupaec103ea62b32zbita
##### BAZ ####################
[Account baz]
localrepository = Local_baz
remoterepository = Remote_baz
...
Jak widać z powyższego, poczta jest pobierana z serwera i zachowywana w podfolderach w ~/POCZTA.
Skrypty dla Launchd uruchamiające agentów offlineimapa
W folderze ~/Library/LaunchAgents/ utworzyłem plisty dla każdego konta. Przykładowo dla konta FOO plik wygląda tak:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.alpine.foo</string>
<key>OnDemand</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>~/bin/offlineimap</string>
<string>-a foo</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>NetworkState</key>
<true/>
</dict>
<key>StandardInPath</key>
<string>/tmp/offlineimap-foo.stdin</string>
<key>StandardOutPath</key>
<string>/tmp/offlineimap-foo.stdout</string>
<key>StandardErrorPath</key>
<string>/tmp/offlineimap-foo.stderr</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>~/bin:/bin:/usr/bin:/usr/local/bin</string>
</dict>
</dict>
</plist>
Uwaga: bardzo ważne jest by dodać odpowiednie ścieżki do zmiennych środowiskowych.
Dyrektywy StandardInPath, StandardOutPath i StandardErrorPath służą mi do sprawdzania czy offlineimap działa bo bywa, że się wysypuje, np. gdy wyłączę sieć przy jakichś eksperymentach. Bywało, że Launchd uruchamiał mi kilka kopii offlineimapa i po jakimś czasie zarzynał system. Jest to szybki hack i nie mam czasu robić czegoś znośniejszego.
Launchd-em ładuję jeszcze dodatkowy skrypt, którego plist jest poniżej:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.poczta-ok</string>
<key>Program</key>
<string>~/bin/alpine_czy_poczta_ok.sh</string>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>60</integer>
<key>StandardInPath</key>
<string>/tmp/poczta-ok.stdin</string>
<key>StandardOutPath</key>
<string>/tmp/poczta-ok.stdout</string>
<key>StandardErrorPath</key>
<string>/tmp/poczta-ok.stderr</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>~/homebrew/bin:/bin:/usr/bin:/usr/local/bin</string>
</dict>
</dict>
</plist>
A sam skrypt wygląda tak:
#!/bin/bash
SERVERS=(foo bar)
for server in ${SERVERS[*]}
do
FILE="/tmp/offlineimap-$server.stdout"
if [ -s $FILE ]
then
MSG=`tail -n 1 $FILE`
ANSWER="$(~/bin/alerter -message "$MSG" -closeLabel POKAŻ -title "`echo $server | tr '[:lower:]' '[:upper:]'`" -sound default -actions NAPRAW -timeout 10)"
fi
if [ "$ANSWER" == "POKAŻ" ]
then
ANSWER="$(~/bin/alerter -message "`tail -n 4 $FILE`" -closeLabel ZAMKNIJ -title "`echo $server | tr '[:lower:]' '[:upper:]'`" -sound default -actions NAPRAW -timeout 10)"
fi
if [ "$ANSWER" == "NAPRAW" ]
then
rm -f $FILE
touch $FILE
fi
if [ "$ANSWER" == "@TIMEOUT" ]
then
rm -f $FILE
touch $FILE
fi
done
Zadaniem tego skryptu jest wykrywanie błędów offlineimapa i pokazywanie ich w postaci Notification (za pomocą alertera: https://github.com/alloy/terminal-notifier) oraz umożliwienia podstawowej ich obłsugi. Polega to na ich kasowaniu i tworzeniu. ;)
Jest jeszcze jeden skrypt, którym od czasu do czasu przeładowuję offlineimapa, nie dodałem go do obsługi bo już się praktycznie przeniosłem na Macbooka pod Debiana, a tam wszystko działa bez zarzutu. Ten skrypt to taki prymityw:
#!/bin/sh
LISTA=`ls -1 ~/Library/LaunchAgents/*.alpine.*.plist`
for i in $LISTA; do
launchctl unload $i
done
for i in $LISTA; do
launchctl load $i
done
launchctl unload ~/Library/LaunchAgents/local.poczta-ok.plist
launchctl load ~/Library/LaunchAgents/local.poczta-ok.plist
Instalacja Alpine
Alpine można zaisntalować z paczki, ja jednak wolałem skompilować go ze źródeł, aby wyposażyć swoją wersję w aktualne patche.
Instalacja paczki:
brew install alpine
Instalacja ze źródeł przebiega następująco:
mkdir Alpine
cd Alpine
wget http://alpine.x10host.com/alpine/release/src/alpine-2.22.tar.xz
tar zxvf alpine-2.22.tar.xz
wget http://alpine.x10host.com/alpine/patches/alpine-2.22/all.patch.gz
gunzip all.patch.gz
cd alpine-2.22
patch -p 1 < ../all.patch
xcode-select --install # instalacja "command line tools" w macOS-ie
./configure --disable-debug --with-passfile=.pine-passfile
make
sudo make install
Warto odwiedzić stronę http://alpine.x10host.com/alpine/ i poczytać co zmieniają w Alpinie poszczególne łaty.
Konfiguracja Alpine
Mój plik jest bardzo długi, więc skupię się na najważnieszych ustawieniach, których Alpine szuka w ~/.pinerc.
Podstawową rzeczą jest podanie serwera wysyłającego pocztę:
smtp-server=mail.foo.pl:587/tls/user=trompka@foo.pl
Następną mega-ważną sprawą jest prawidłowe ustawienie ścieżek do plików poczty pobranych przez offlineimapa, u mnie każde konto ma własny podfolder w folderze ~/POCZTA, czyli dla trzech kont foo, bar i baz, wygląda to tak:
~
|____POCZTA
|____FOO
|____BAR
|____BAZ
Zatem dla konta FOO (mojego domyślnego) ścieżka do Inboxa to:
inbox-path=#md/POCZTA/FOO/inbox
Pozostałe Inboksy są w tzw. kolekcji (dodałem konto BAZ, żeby łatwiej było zrozumieć):
# Lista pozostałych Inboxów, poza głównym
incoming-folders=#md/POCZTA/BAR/inbox, #md/POCZTA/BAZ/inbox
# Lista folderów, do których trafiają zachowane emaile, pierwszy jest folderem domyślnym (w moim pzypadku: dla konta FOO)
folder-collections=FOO #md/POCZTA/FOO/[],
BAR #md/POCZTA/BAR/[],
BAZ #md/POCZTA/BAZ/[]
# Ścieżka względna do homedira, w której leżą foldery z moją pocztą
maildir-location=POCZTA
Jeszcze ustawienie wymuszające na Alpine, żeby po starcie wyświetlał indeks emaili w Inboksie i podświetlił najnowszy email:
initial-keystroke-list=I,
j,
^v
Alpine można bardzo ściśle dopasować do własnych przyzwyczajeń ale wymaga to porządnego zapoznania się z opcjami dostępnymiu w programie, przy każdej z nich znajduje się obszerna Pomoc w języku angielskim. Naprawdę warto to przeczytać, serdecznie polecam tzw. Role pozwalające na kolorowanie emaili czy uruchamianie własnych poleceń np. na podstawie adresu nadawcy, itp.