Table of Contents
IMAP protocol
Example of an IMAP session:
$ telnet mail.texnet.it 143 Trying 217.19.150.6... Connected to mail.texnet.it. Escape character is '^]'. * OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS] Courier-IMAP ready. Copyright 1998-2005 Double Precision, Inc. See COPYING for distribution information. a1 CAPABILITY * CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS a1 OK CAPABILITY completed a2 LOGIN niccolo ******** a2 OK LOGIN Ok. a3 LIST "" "*" * LIST (\Marked \HasNoChildren) "." "INBOX" a3 OK LIST completed a4 SELECT INBOX * FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent) * OK [PERMANENTFLAGS (\* \Draft \Answered \Flagged \Deleted \Seen)] Limited * 2856 EXISTS * 2856 RECENT * OK [UIDVALIDITY 1163517848] Ok * OK [MYRIGHTS "acdilrsw"] ACL a4 OK [READ-WRITE] Ok a5 FETCH 5 FAST * 5 FETCH (FLAGS (\Recent) INTERNALDATE "25-Nov-2005 22:09:41 +0100" RFC822.SIZE 2763) a5 OK FETCH completed. a6 FETCH 3 (flags body[header.fields (subject)]) * 3 FETCH (FLAGS (\Recent) BODY[HEADER.FIELDS ("subject")] {94} Subject: Cron <clamav@pierargo> [ -x /usr/bin/freshclam ] && /usr/bin/freshclam >/dev/null ) * 3 FETCH (FLAGS (\Seen \Recent)) a6 OK FETCH completed. a7 LOGOUT
Some IMAP servers present all the folders as subfolders of the INBOX:
a3 LIST "" "*" * LIST (\HasNoChildren) "." "INBOX.Sent" * LIST (\HasNoChildren) "." "INBOX.Trash" * LIST (\HasNoChildren) "." "INBOX.Spam" * LIST (\Marked \HasChildren) "." "INBOX" a4 CREATE INBOX.Archive
For other IMAP servers, the folders are outside the INBOX:
a3 LIST "" "*" * LIST (\HasNoChildren) "." Spam * LIST (\HasNoChildren \Drafts) "." Drafts * LIST (\HasNoChildren \UnMarked \Sent) "." Sent * LIST (\HasNoChildren \Trash) "." Trash * LIST (\HasNoChildren) "." INBOX a4 CREATE Archive
Migrating IMAP folder
offlineimap
Sincronizza una cartella su server IMAP remoto con una Maildir locale oppure un altro server IMAP. Sembra il programma più flessibile e semplice da utilizzare rispetto a isync, mailsync, interimap, imapsync e imapcopy..
ATTENZIONE Le versioni 6.3.4 di Debian Wheezy e 6.5.4 hanno diversi bug.
ATTENZIONE La versione 7.3.0 (git20210225) di Debian 11.3 Bullseye ha un bug con le cartelle IMAP che contengono degli spazi (vedere pull risolutivo #80). Un rimedio temporaneo è creare manualmente la cartella IMAP sul server ricevente. Esiste il pacchetto offlineimap3_0.0~git20211018.e64c254+dfsg-1~bpo11+1_all.deb in bullseye-backports.
ATTENZIONE Il programma effettua una sincronizzazione bidirezionale, ma noi siamo interessati alla migrazione di una mailbox da un server ad un altro, pertanto la bidirezionalità è un rischio. In caso di confusione sul nome delle cartelle tra i due repository e sullo stato dell'ultima sincronizzazione, c'è il rischio concreto di eliminare i messaggi dal server di origine.
ATTENZIONE La versione 8.0.0 (Debian GNU/Linux 12 Bookworm) non riesce a gestire correttamente la sincronizzazione con server Courier IMAP in presenza di sottocartelle di primo livello o ulteriori. Vedere l'issue #188.
Pertanto, prima di iniziare la sincronizzazione, è opportuno indagare quali cartelle sono presenti sul server di origine e il loro percorso. Inoltre, se si cambia il file di configurazione, è opportuno rimuovere tutti i file di stato che vengono salvati in $HOME/.offlineimap/ relativi ad Account-* e Repository-*.
Esempio #1: da IMAP a Maildir
Il primo esempio riguarda una migrazione da repository IMAP remoto a Maildir locale. Prepariamo il file di configurazione offlineimap-imap-maildir.conf:
[general] accounts = Test [Account Test] remoterepository = RemoteIMAP localrepository = Localhost [Repository RemoteIMAP] type = IMAP # Strip the "INBOX" prefix when copying to a local Maildir, examples: # 'INBOX' => '.' # 'INBOX.Trash' => '.Trash' # 'INBOX.Sent' => '.Sent' nametrans = lambda foldername: re.sub('^INBOX\.*', '.', foldername) remotehost = mail.example.org remoteuser = username remotepass = MySecret createfolders = False sslcacertfile = /usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt ssl_version = tls1_2 # If you don't want IMAPS on port 993, you can use STARTTLS on port 143. #ssl = no #starttls = yes [Repository Localhost] type = Maildir localfolders = /home/username2/Maildir
Per impostazione predefinita offlineimap tenta una connessione SSL su porta 993/TCP, verificando il certificato del server remoto. Senza l'opzione sslcacertfile il client offlineimap non è in grado di inziare la sessione TLS e si blocca con il seguente errore:
offlineimap.error.OfflineImapError: No CA certificates and no server fingerprints configured. You must configure at least something, otherwise having SSL helps nothing.
Per vedere quale Certification Authority deve essere usata è necessario recuperare il certificato SSL dal server remoto, ad esempio con il comando:
openssl s_client -showcerts -connect mail.example.org:993
Quindi si ispeziona la certificate chain alla ricerca di Organization e Common Name con valori del tipo:
- O = Actalis S.p.A., CN = Actalis Organization Validated Server CA G3
- O = Let's Encrypt, CN = R3
Avendo installato il pacchetto ca-certificates, si cerca nella directory /usr/share/ca-certificates/mozilla/ il certificato giusto da usare. Dopo aver abilitato SSL si può incappare anche nel seguente errore:
[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:727)
Questo significa che il server utilizza una versione debole di SSL, vulnerabile ad attacchi del tipo Factoring RSA Export Keys poiché usa una chiave Diffie-Hellman più corta di 768 byte. In questo caso, se non possiamo correggere il server, è necessario aggiungere l'opzione di configurazione ssl_version = tls1_2
.
Se si desidera utilizzare una connessione con STARTTLS su porta 143, è necessario aggiungere le opzioni ssl = no
e starttls = yes
.
Si esegue il programma in modalità --info, senza alcun trasferimento di messaggi:
offlineimap --dry-run --info -c ./offlineimap-imap-maildir.conf
Nell'output si legge:
... Remote repository 'RemoteIMAP': type 'IMAP' ... Folderlist: INBOX -> INBOX.Drafts -> .Drafts INBOX.Archives.2019 -> .Archives.2019 INBOX.Sent -> .Sent INBOX.Spam -> .Spam INBOX.Trash -> .Trash Local repository 'Localhost': type 'Maildir' Folderlist:
Come si vede il server di origine, oltre alla cartella INBOX, presenenta alcune sottocartelle che hanno il prefisso INBOX.; la regola re.sub() nel file di configurazione serve a tradurre il nome delle cartelle dalla nomenclatura IMAP remota alla Maildir locale (ovviamente si deve verificare lo standard adottato dal server IMAP che gira sull'host di destinazione). In particolare:
- La INBOX deve essere la cartella radice della Maildir.
- Il prefisso INBOX delle sottocartelle deve essere rimosso.
- Ogni sottocartella deve avere il punto come prefisso del nome (directory nascosta Unix).
Vengono create le cartelle $HOME/.offlineimap/Repository-RemoteIMAP/ e $HOME/.offlineimap/Repository-Localhost/, per il momento vuote, ma che conterranno poi lo stato della sincronizzazione.
Esempio #2: da IMAP a IMAP
In questo esempio di effettua la sincronizzazione fra due server IMAP, quindi senza fare accesso diretto al filesystem. Questo il file di configurazione offlineimap-imap-imap.conf:
[general] accounts = Test [Account Test] remoterepository = RemoteIMAP localrepository = LocalIMAP [Repository RemoteIMAP] type = IMAP # Strip the "INBOX" prefix when copying to a destination IMAP. # 'INBOX' => 'INBOX' # 'INBOX.Trash' => 'Trash' # 'INBOX.Sent' => 'Sent' nametrans = lambda foldername: re.sub(r'^INBOX\.', '', foldername) remotehost = mail1.example.org remoteuser = username1 remotepass = MySecret1 createfolders = False sslcacertfile = /usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt [Repository LocalIMAP] type = IMAP remotehost = mail2.example.org remoteuser = username2 remotepass = MySecret2 sslcacertfile = /usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt
Si esegue il programma in modalità --info:
offlineimap --dry-run --info -c ./offlineimap-imap-imap.conf
Verifichiamo l'output:
Remote repository 'RemoteIMAP': type 'IMAP' ... Folderlist: INBOX.Drafts -> Drafts INBOX INBOX.Sent -> Sent INBOX.Spam -> Spam INBOX.Trash -> Trash Local repository 'LocalIMAP': type 'MappedIMAP' ... Folderlist: Drafts INBOX Sent Spam Trash
Si capisce che i due server IMAP utilizzano una struttura diversa: il primo ha il prefisso INBOX.
per ogni sottocartella, mentre il secondo no. Anche in questo caso è stato necessario utilizzare l'opzione nametrans con una opportuna re.sub() leggermente diversa dall'esempio #1. Si verifica comunque che il nome INBOX
non viene trasformato, mentre per le sottocartelle avviene la corretta trasformazione che consiste semplicememte nel rimuovere il prefisso INBOX.
, compreso il punto.
Sincronizzazione
La sincronizzazione avviene semplicemente eseguendo il comando con l'opportuno file di configurazione. In questo esempio si esegue un thread singolo (opzione -1) e si scrive nel file di log (opzione -l) il debug del protocollo imap e maildir (opzione -d):
offlineimap -1 -c offlineimap-imap-imap.conf -d imap,maildir -l offlineimap.log
- Lo stato della sincronizzazione viene scritto in
$HOME/.offlineimap/
- La
Maildir
locale può essere anche vuota, viene riempita opportunamente. - Potrebbe essere necessario specificare l'opzione
nametrans
per entrambi i repository, in modo che la sincronizzazione bidirezionale crei le giuste cartelle sul server remoto, ma noi abbiamo preferito utilizzare l'opzionecreatefolders = False
in modo che non vi sia propagazione di cartelle verso il server origine.
Soluzione problemi
isync
Consente la sincronizzazione di una Maildir locale con un server IMAP remoto.
- Errore
malformed UIDVALIDITY status
, compilata versione 1.0.6 al posto della versione 1.0.4 fornita da Debian Jessie. - Esiste un modo di fare trasferimento ricorsivo di tutte le cartelle? Provare l'opzione
-1
- Problemi con le cartelle che contengono spazi nel nome, vedere la soluzione di eseguire direttamente
mbsync
. - Lo stato della sincronizzazione viene scritto in ogni Maildir nel file
.mbsyncstate
.
Uso diretto di mbsync
Per il problema delle cartelle che contengono spazi nel nome, si lancia isync --write
. Viene generato un file mbsync.conf
che deve essere corretto a mano aggiungendo le doppie virgolette. Quindi si esegue:
mbsync --config mbsync.conf <channel_name>
mailsync
Consente la sincronizzazione di un server IMAP remoto con il filesystem locale (non Maildir) oppure altro server IMAP.
Non supporta il formato Maildir su filesystem locale. Il programma in effetti si appoggia sulla libreria c-client per accedere agli archivi di posta, in passato Debian includeva una patch per supportare Maildir, ma questa patch è stata rimossa (verificato in libc-client2007e di Debian Jessie).
Con questo file di configurazione mailsync.conf si sincronizza un server IMAP (remoto) con uno che gira in localhost:
store first-server { server {mail.server1.it/user=user1/novalidate-cert} ref {mail.server1.it} pat * prefix INBOX passwd FirstSecret } store second-server { server {localhost/user=user2/novalidate-cert} ref {localhost} pat * prefix INBOX passwd SecondSecret } channel first-to-second first-server second-server { msinfo .msinfo }
Per lanciare la sincronizzazione per la prima volta si cancella un eventuale file di stato .msinfo
:
rm .msinfo mailsync -v -d -di -dc -f mailsync.conf first-to-second
interimap
Effettua la sincronizzazione fra due server IMAP, ma richiede la capability QRESYNC su entrambi.
imapsync
Non presente in Debian 10 Buster. Obsoleto?
To migrate an IMAP account from one host1 to host2, there is the imapsync
tool. In this usage example mail messages not longer existing on host1 will be deleted also on host2:
#!/bin/sh login1=username_on_host1 passwd1=SecretOnHost1 login2=username_on_host2 passwd2=SecretOnHost2 ./imapsync \ --host1 83.145.162.149 \ --authmech1 LOGIN \ --user1 "$login1" \ --password1 "$passwd1" \ --subscribed \ --host2 127.0.0.1 \ --authmech2 LOGIN \ --user2 "$login2" \ --password2 "$passwd2" \ --subscribe \ --delete2 --expunge2
Problema con allegati con BODY vuoti: invece di saltare il messaggio il programma si blocca.
imapcopy
Non presente in Debian 10 Buster. Obsoleto?
Il tool non supporta SSL né TLS, inoltre non effettua una sincronizzazione, ma una copia; quindi se viene eseguito due volte i messaggi vengono duplicati.
Si prepara un file di configurazione $HOME/ImapCopy.cfg
con le seguenti opzioni:
SourceServer host1 SourcePort 143 DestServer host2 DestPort 143 converttimezone "UTC" "+0000" converttimezone "UT" "+0000" Copy "login1" "password1" "login2" "password2"
Lanciare il comando con l'opzione -l
in modo che venga creato il file di log imapcopy.log
.
Quota
Il protocollo IMAP supporta un meccanismo di “quota volontaria”, cioè i vari software (SMTP, IMAP, POP) devono collaborare a mantenere aggiornato un file con le statistiche di occupazione.
Per vedere se il server IMAP supporta correttamente la quota:
telnet 127.0.0.1 143 * OK [CAPABILITY IMAP4rev1 UIDPLUS ... QUOTA ...] Courier-IMAP ready. a1 LOGIN niccolo MySecret a1 OK LOGIN Ok. a2 GETQUOTAROOT INBOX * QUOTAROOT "INBOX" "ROOT" * QUOTA "ROOT" (STORAGE 6417 19532) a2 OK GETQUOTAROOT Ok. a3 LOGOUT
In questo caso il Courier-IMAP implementa una soft-quota, cioè non quella del kernel Linux. Questa softquota è mantenuta nel file ~/Maildir/maildirsize
e bisogna che tutti i programmi che scrivono/leggono nella Maildir lo tengano aggiornato. Ad esempio procmail
non lo fa.
Per aggiornare una-tantum il contenuto del file (modificando lo spazio disponibile):
maildirmake -q 20000000S Maildir
I programmi courier-imap
e courier-pop
si comportano correttamente se trovano il file ~/Maildir/maildirsize
, cioè aggiornano il totale dello spazio occupato quando viene eliminato un messaggio.
L'aggiornamento di maildirsize
all'arrivo di nuovi messaggi non viene fatto direttamente da Postfix o Exim, si deve utilizzare un opportuno filtro di consegna, come maildrop
.
Se qualcuno interviene direttamente sui file nella Maildir, è necessario rigenerare il file maildirsize
come visto sopra.
FAM/Gamin library
Il server Courier IMAP sfrutta il supporto FAM (File Alteration Monitor) o Gamin. Conviene installare il pacchetto Debian gamin. Se non è installata una di queste librerie produce i seguente messaggio di errore:
* OK [ALERT] Filesystem notification initialization error -- contact your mail administrator (check for configuration errors with the FAM/Gamin library)
Courier IMAP
La connessione cifrata STARTTLS si appoggia su Courier authdaemon. Per effettuare debug lato client si può usare Firefox attivando la Console degli errori dal menu Strumenti. Durante l'aggiornamento da Weezy a Jessie ad esempio si deve risolvere il problema del file /etc/courier/dhparams.pem
che deve passare da 1024 ad almeno 2048 bit.