diff options
author | Matěj Cepl <mcepl@cepl.eu> | 2018-04-22 02:08:10 +0200 |
---|---|---|
committer | Matěj Cepl <mcepl@cepl.eu> | 2018-04-22 02:09:31 +0200 |
commit | cc4355020267315ed431472cd89e4ec46c873f0d (patch) | |
tree | ca479b52f4abfec4a32f4cdc181c701dfc501b56 | |
parent | ca9285e80b9fa2df82b135b3684f933d05222f69 (diff) | |
download | imapArch-cc4355020267315ed431472cd89e4ec46c873f0d.tar.gz |
Remove previous attemps which are now obsolete.
Also add some missing RFCs.
-rw-r--r-- | expireIMAP.pl | 35 | ||||
-rw-r--r-- | previousAttempts/archiveIMAP.pl | 144 | ||||
-rw-r--r-- | previousAttempts/java/ArchivableFolder.java | 69 | ||||
-rw-r--r-- | previousAttempts/java/Archives.java | 85 | ||||
-rw-r--r-- | previousAttempts/java/imapList.java | 95 | ||||
-rw-r--r-- | previousAttempts/jython/imapArchive.py | 205 | ||||
-rw-r--r-- | previousAttempts/jython/purgeObsolete.py | 151 | ||||
-rw-r--r-- | previousAttempts/jython/purgeObsoleteTest.py | 43 | ||||
-rw-r--r-- | standards/rfc2177.txt | 227 | ||||
-rw-r--r-- | standards/rfc4315.txt | 451 | ||||
-rw-r--r-- | standards/rfc6851.txt | 451 |
11 files changed, 902 insertions, 1054 deletions
diff --git a/expireIMAP.pl b/expireIMAP.pl deleted file mode 100644 index 5f00651..0000000 --- a/expireIMAP.pl +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Mail::IMAPClient; -use Data::Dumper; -use DateTime; - -my $hostname = "localhost"; -my $login = "matej"; -my $passwd = "lubdkc"; - -die "Just one name of the folder, please." unless $#ARGV == 0; - -# How many months before today the cut date should be? -my $howManyMonths = 3; -my $lengthOfScreen = 65; - -my $imap = Mail::IMAPClient->new(); -$imap = Mail::IMAPClient->new( - Server => $hostname, - User => $login, - Password => $passwd, - UID => 1 -) or die "Cannot connect to localhost as matej: $@"; - -my $cutDate = DateTime->now(); -$cutDate->add( months => -$howManyMonths ); - -# Do the stuff! -$imap->select($ARGV[0]); -my @msgsProc = $imap->search(" UNDELETED BEFORE " . $cutDate->strftime("%d-%b-%Y")); -print "\$#msgsProc = $#msgsProc\n"; -$imap->delete_message(@msgsProc) or die "Cannot delete $#msgsProc messages."; -$imap->close();
\ No newline at end of file diff --git a/previousAttempts/archiveIMAP.pl b/previousAttempts/archiveIMAP.pl deleted file mode 100644 index a1833de..0000000 --- a/previousAttempts/archiveIMAP.pl +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Mail::IMAPClient; -use IO::Socket::SSL; -use Data::Dumper; -use DateTime; -use DateTime::Format::Strptime; -use Config::IniFiles; - -# possible values are currently -- zimbra, localhost, pobox -my $account = "localhost"; - -# How many months before today the cut date should be? -my $howManyMonths = 3; -my $debug = 0; - -# get configuration for the account -my $conf = Config::IniFiles->new( -file => "/home/matej/.bugzillarc"); -die "No configuration for account $account" unless $conf->SectionExists($account); -my $hostname = $conf->val($account,'host'); -my $login = $conf->val($account,'name'); -my $password = $conf->val($account,'password'); -my $ssl= $conf->val($account,'ssl'); - -sub getTargetFolder { - my $source = shift; - my $year = shift; - - $source =~ s/^\/*(.*)\/*$/$1/; - return "/INBOX/Archiv/" . $year . '/' . $source; -} - -# makes sure that the folder including its parents -# RFC2060 says in 6.3.3 that server SHOULD create -# parents, so just to be sure if it doesn't. -sub assureFolder { - my $imaphandle = shift; - my $fullfoldername = shift; - my $sep = $imap->separator($fullfoldername); - - if ($imaphandle->exists($fullfoldername)) { - return 1; - } - my $parentpath = join ($sep, - (split /$sep/,$fullfoldername)[0,-1] - ); - assureFolder($imaphandle,$parentpath); - $imaphandle->create($fullfoldername) or - die "Unable to create folder $fullfoldername"; -} - -our $Strp = new DateTime::Format::Strptime( - pattern => '%a, %d %b %Y %H:%M:%S %z' -); -our $StrpNoTZ = new DateTime::Format::Strptime( - pattern => '%a, %d %b %Y %H:%M:%S' -); - -sub getMessageYear { - my $msgStr = shift; - my $msgDt = $Strp->parse_datetime($msgStr); - - if (!$msgDt) { - $msgDt = $StrpNoTZ->parse_datetime($msgStr); - } - if (!$msgDt) { - print "Date EMPTY.\n"; - return ""; # TODO: message without Date: - # not sure what to do about it - # Currently just do nothing and - # return empty string. - } - my $year = $msgDt->year; - if ($debug) { - print "\$msgStr = $msgStr, \$msgDt = $msgDt, year = $year\n"; - } - - return $year; -} - -my $imap = Mail::IMAPClient->new(); -if ($ssl) { - my $sslSocket=IO::Socket::SSL->new("$hostname:imaps"); - die ("Error connecting - $@") unless defined $sslSocket; - $sslSocket->autoflush(1); - - $imap = Mail::IMAPClient->new( - Server => $hostname, - Socket => $sslSocket, - User => $login, - Debug => $debug, - Password => $password, - UID => 1 - ) or die "Cannot connect to localhost as matej: $@"; -} else { - $imap = Mail::IMAPClient->new( - Server => $hostname, - User => $login, - Debug => $debug, - Password => $password, - UID => 1 - ) or die "Cannot connect to localhost as matej: $@"; -} - -my $cutDate = DateTime->now(); -$cutDate->add( months => -$howManyMonths ); - -my @sourceFolders = grep(!/^INBOX\/Archiv/,$imap->folders()); -my %targetedMessages; -my ($msgYear,$msgDateStr,$targetFolder); - -foreach my $folder (@sourceFolders) { - $imap->select($folder); - die "Cannot select folder $folder\n" if $@; - my @msgsProc = $imap->search(" UNDELETED BEFORE " . $cutDate->strftime("%d-%b-%Y")); - if ($#msgsProc > 0) { - print "Move $#msgsProc in $folder.\n"; - foreach my $msg (@msgsProc) { - $msgYear = getMessageYear($imap->date($msg)); - if ($msgYear !~ /^\s*$/) { - $targetFolder = getTargetFolder($folder,$msgYear); - if ($debug) { - print "Move message $msg from the folder $folder to $targetFolder.\n"; - } - push ( @{ $targetedMessages{$folder} } , $msg); - } - } - } - foreach my $tFolder (keys %targetedMessages) { - if (!($imap->exists($tFolder))) { - # Not sure how would following deal with non-existent - # parent folder, so rather recursively create - # parents. - # - #$imap->create($tFolder) - # or die "Could not create $tFolder: $@\n"; - assureFolder($imap,$tFolder); - } - $imap->move($tFolder,$targetedMessages{$tFolder}); - } -} -$imap->close();
\ No newline at end of file diff --git a/previousAttempts/java/ArchivableFolder.java b/previousAttempts/java/ArchivableFolder.java deleted file mode 100644 index 47a5764..0000000 --- a/previousAttempts/java/ArchivableFolder.java +++ /dev/null @@ -1,69 +0,0 @@ -import java.util.ArrayList; - -import javax.mail.Flags; -import javax.mail.Folder; -import javax.mail.Message; -import javax.mail.MessagingException; - -/** - * Class servers as a container for messages to be archived from the - * particular folder and does the actual archivation. - * @author matej - * - */ -@SuppressWarnings("serial") -public class ArchivableFolder extends ArrayList<Message> { - private Folder sourceFolder; - private Folder targetFolder; - - /** - * Constructor for the folder. - * @param source - * @param year - * @throws MessagingException - */ - public ArchivableFolder(Folder source, int year) throws MessagingException { - sourceFolder = source; - targetFolder = getArchiveFolderName(source,year); - } - - /** - * - * @throws MessagingException - */ - public void doArchive() throws MessagingException { - Message[] intArray; - intArray = (Message[]) this.toArray(); - sourceFolder.copyMessages(intArray, targetFolder); - for (Message message : intArray) { - message.setFlag(Flags.Flag.DELETED, true); - } - sourceFolder.expunge(); - } - - /** - * - * @param msg - * @return - */ - @Override - public boolean add(Message msg) { - return this.add(msg); - } - - /** - * - * @param folder - * @param year - * @return - * @throws MessagingException - */ - private static Folder getArchiveFolderName(Folder folder,int year) throws MessagingException { - String archFolder = "INBOX/Archiv/"; - int rootLen = "INBOX/".length(); - String baseName = folder.getFullName(); - baseName = baseName.substring(rootLen, baseName.length()); - archFolder = "/" + archFolder + year + "/" + baseName; - return(folder.getFolder(archFolder)); - } -} diff --git a/previousAttempts/java/Archives.java b/previousAttempts/java/Archives.java deleted file mode 100644 index c882e75..0000000 --- a/previousAttempts/java/Archives.java +++ /dev/null @@ -1,85 +0,0 @@ -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.HashMap; - -import javax.mail.Folder; -import javax.mail.Message; -import javax.mail.MessagingException; - -/** - * - */ - -/** - * @author matej - * - */ -@SuppressWarnings("serial") -public class Archives extends HashMap<Object[],ArchivableFolder> { - - public Archives() { - ; - } - - /** - * create a key for the list - * @param fldName String with the full name of the folder - * @param year int of the year of the messages to be stored - * there - * @return array consisting from the both parameters of - * this function. - */ - private Object[] createKey(String fldName, int year) { - Object[] out = {fldName,year}; - return(out); - } - - /** - * Find out whether the object with the key consisting of - * the folder name and year exists in this object. - * - * @param fld Folder where the message is stored - * @param year int year of the message date - * @return boolean saying whether the folder for this message - * has been already added to this object. - */ - private boolean search(Folder fld, int year) { - Object[] key = createKey(fld.getFullName(), year); - return(this.containsKey(key)); - } - - /** - * Return the date of the message - * - * @param msg analyzed message - * @return GregorianCalendar of the messages date - * @throws MessagingException - */ - static GregorianCalendar getMessageDate(Message msg) - throws MessagingException { - GregorianCalendar date = new GregorianCalendar(); - date.setTime(msg.getReceivedDate()); - return(date); - } - - /** - * Check whether the ArchivableFolder (@see ArchivableFolder) - * for the particular year actually exists, and if not then create - * it. In any event add - * @param msg - * @throws MessagingException - */ - public void add(Message msg) throws MessagingException { - Folder fld = msg.getFolder(); - GregorianCalendar msgDate = getMessageDate(msg); - int year = msgDate.get(Calendar.YEAR); - - if (!search(fld,year)) { - ArchivableFolder archfld = new ArchivableFolder(fld,year); - Object[] key = createKey(fld.getFullName(), year); - this.put(key, archfld); - } - } - -// public ArchivableFolder get() -}
\ No newline at end of file diff --git a/previousAttempts/java/imapList.java b/previousAttempts/java/imapList.java deleted file mode 100644 index fd2ef1d..0000000 --- a/previousAttempts/java/imapList.java +++ /dev/null @@ -1,95 +0,0 @@ -import java.io.File; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.Properties; -import java.util.prefs.BackingStoreException; -import java.util.prefs.Preferences; - -import javax.mail.Folder; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.NoSuchProviderException; -import javax.mail.Session; -import javax.mail.Store; - -import org.ini4j.IniFile; - -/** testing class for javax.mail functions - * @author matej - * - */ -public class imapList { - private static Archives archiveList = new Archives(); - private static GregorianCalendar threeMonthAgo = - new GregorianCalendar(); - - private static void archiveFolder(Folder fld) throws MessagingException { - fld.open(Folder.READ_WRITE); - - for (Message msg : fld.getMessages()) { - GregorianCalendar msgDate = Archives.getMessageDate(msg); - System.out.println(msgDate); - if (msgDate.before(threeMonthAgo)) { - archiveList.add(msg); - } - } - - fld.close(false); - } - - /** - * main() method setting up internal properties and then running - * remaining classes and methods. - * @param args - * @throws BackingStoreException - * @throws MessagingException - */ - public static void main(String[] args) throws BackingStoreException, MessagingException { - Store store = null; - String folderName = ""; - - Properties props = System.getProperties(); - String homeFolder = props.getProperty("user.home"); - props.setProperty("javax.net.ssl.keyStore", - homeFolder+"/.keystore"); - props.setProperty("javax.net.ssl.trustStore", - homeFolder+"/.keystore"); - - String iniFileName = homeFolder+"/.bugzillarc"; - Preferences prefs = new IniFile(new File(iniFileName)); - String login = prefs.node("localhost").get("user", - props.getProperty("user.name")); - String password = prefs.node("localhost").get("password", null); - String hostname = prefs.node("localhost").get("host", "localhost"); - int port = prefs.node("localhost").getInt("port", 993); - - threeMonthAgo = (GregorianCalendar) Calendar.getInstance(); - threeMonthAgo.set(Calendar.MONTH, - threeMonthAgo.get(Calendar.MONTH)-3); - - Session session = Session.getInstance(props,null); - //session.setDebug(true); - try { - store = session.getStore("imaps"); - } catch (NoSuchProviderException e) { - System.out.println(e.getMessage()); - System.exit(1); - } - try { - store.connect(hostname, port, login, password); - } catch (MessagingException e) { - System.out.print(e.getMessage()); - System.exit(1); - } - Folder folder = store.getDefaultFolder(); - Folder inboxfolder = folder.getFolder("INBOX"); - Folder[] folderList = inboxfolder.list("*"); - for (Folder fld : folderList) { - folderName = fld.getFullName(); - if (!folderName.startsWith("INBOX/Archiv")) { - archiveFolder(fld); - } - } - store.close(); - } -}
\ No newline at end of file diff --git a/previousAttempts/jython/imapArchive.py b/previousAttempts/jython/imapArchive.py deleted file mode 100644 index f965c95..0000000 --- a/previousAttempts/jython/imapArchive.py +++ /dev/null @@ -1,205 +0,0 @@ -# -*- coding: utf-8 -*- -# note http://docs.python.org/lib/module-doctest.html -# resp. file:///usr/share/doc/python-docs-*/html/lib/module-doctest.html -# for testing -from __future__ import division -from java.util import Properties, Date -from java.lang import System -from javax.mail import * -from jarray import array -import sys, os -from datetime import date -from ConfigParser import ConfigParser - -debug=False - -def __getMessageDate(msg): - """ - Return the date of the message - - @param msg analyzed message - @return GregorianCalendar of the messages date - @throws MessagingException - """ - dateMS = msg.getReceivedDate().getTime()//1000 - dateStruct = date.fromtimestamp(dateMS) - return dateStruct - -class ArchivableFolder(list): - def __init__(self,source,year): - """ - Constructor for the folder. - - @param source folder from the messages should be archived - @param year int of the year for which the messages are - archived - """ - self.sourceFolder = source - targetName = self.__getArchiveFolderName(source.getFullName(), year) - self.targetFolder = self.sourceFolder.getFolder(targetName) - - def __getArchiveFolderName(self,srcFldName,year): - """ - @param folder string with the folder name - @param year int - @return - """ - archFolder = "INBOX/Archiv/" - rootLen = len("INBOX/") - if not(srcFldName[:rootLen]=="/INBOX/"): - raise FolderNotFoundException(\ - "We expect all folders to be under INBOX folder.") - baseName = srcFldName[rootLen:] - archFolder = "/" + archFolder + year + "/" + baseName - return archFolder - - def add(self,msg): - self.append(msg) - - def doArchive(self): - if debug: - for message in self: - print >>sys.stderr, "Moving %s from %s to %s." \ - % (message,self.sourceFolder.getFullName(), - self.targetFolder.getFullName()) - else: - self.sourceFolder.copyMessages(array(self,Message),\ - self.targetFolder) - for message in self: - message.setFlag(Flags.Flag.DELETED, true) - self.sourceFolder.expunge() - -class Archives(dict): - """Collects archivable folders indexed by tuple of - folderName and year - """ - def __init__(self): - pass - - def add(self,msg): - """ - Check whether the ArchivableFolder (@see ArchivableFolder) - for the particular year actually exists, and if not then create - it. In any event add - @param msg - """ - fld = msg.getFolder() - msgDate = __getMessageDate(msg) - year = msgDate.year - - if not(self.search(fld, year)): - archfld = ArchivableFolder(fld,year) - self[self.__createKey(fld,year)] = archfld - - def __createKey(self,name,year): - """ - Create a key for the list - @param fldName String with the full name of the folder - @param year int of the year of the messages to be stored - there - @return tuple consisting from the both parameters of - this function. - """ - return(name,year) - - def search(self,fld,year): - """ - Find out whether the object with the key consisting of - the folder name and year exists in this object. - - @param fld Folder where the message is stored - @param year int year of the message date - @return boolean saying whether the folder for this message - has been already added to this object. - """ - key = self.__createKey(fld.getFullName(), year) - return self.has_key(key) - - def archive(self): - for key in self: - self.doArchive() - -class ArchivedStore(object): - def __init__(self,paramServer="localhost",paramUser="",paramPassword=""): - self.props = System.getProperties() - self.session = Session.getInstance(self.props,None) - self.props.setProperty("javax.net.ssl.keyStore", "/home/matej/.keystore") - self.props.setProperty("javax.net.ssl.trustStore", "/home/matej/.keystore") - if debug: - self.session.setDebug(True) - try: - self.store = self.session.getStore("imaps") - except: - print >> sys.stderr, "Cannot get Store" - raise - - self._threeMonthAgo = date.today() - newmonth = self._threeMonthAgo.month-3 - self._threeMonthAgo = self._threeMonthAgo.replace(month=newmonth) - - conffile = os.path.expanduser("~/.bugzillarc") - confUser = ConfigParser() - defSection = "localhost" - user,host,port,password = self.props.getProperty("user.name"),\ - "localhost",993,"" - if confUser.read(conffile): - if confUser.has_section(defSection): - if confUser.has_option(defSection, "name"): - user = confUser.get(defSection, "name") - if confUser.has_option(defSection, "host"): - host = confUser.get(defSection, "host") - if confUser.has_option(defSection, "port"): - port = confUser.get(defSection, "port") - if confUser.has_option(defSection, "password"): - password = confUser.get(defSection, "password") - - if paramServer: - host=paramServer - if paramUser: - user=paramUser - if paramPassword: - password=paramPassword - - print >>sys.stderr,"host = %s, user = %s, password = %s" % \ - (host,user,password) - - self.__login(host,user,password) - - def __login(self,server,user,password): - try: - self.store.connect(server,user,password) - except: - print >> sys.stderr, "Cannot connect to %s as %s with password %s" %\ - (server,user,password) - raise - - def archive(self): - inboxfolder = self.store.getDefaultFolder().getFolder("INBOX") - folderList=inboxfolder.list('*') - - for folder in folderList: - if folder.getFullName()[:len("INBOX/Archiv")] != "INBOX/Archiv": - archMsgsCnt = self.__archiveFolder(folder) - #folder.close(False) - print "Processed messages = %d" % archMsgsCnt - - def __archiveFolder(self,fld): - fld.open(Folder.READ_WRITE) - for msg in fld.getMessages(): - msgDate = __getMessageDate(msg) - print >>sys.stderr,str(msgDate),str(self._threeMonthAgo) - if msgDate < self._threeMonthAgo: - archFolder = self.__getArchiveFolderName(msg) -# print >> sys.stderr, archFolder -# fld.copyMessages(array([msg],type(msg)), archFolder) -# msg.setFlag(Flags.Flag.DELETED, true) - print "%s -> %s : %s" % (fld.getFullName(), - archFolder.getFullName(),msgDate) - folderLen = len(fld.getMessages()) - fld.close(False) - return(folderLen) - -if __name__=='__main__': - myStore = ArchivedStore(paramPassword="lubdkc") - myStore.archive() - myStore.store.close()
\ No newline at end of file diff --git a/previousAttempts/jython/purgeObsolete.py b/previousAttempts/jython/purgeObsolete.py deleted file mode 100644 index 4491eec..0000000 --- a/previousAttempts/jython/purgeObsolete.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -# note http://docs.python.org/lib/module-doctest.html -# resp. file:///usr/share/doc/python-docs-*/html/lib/module-doctest.html -# for testing -from __future__ import division -from java.util import Properties, Date, GregorianCalendar, Locale -from java.text import SimpleDateFormat -from java.lang import System -from javax.mail import * -from javax.mail.search import * -from com.sun.mail.imap import IMAPFolder, IMAPSSLStore -from jarray import array -import sys, os -from datetime import date -import ConfigParser - -debug=False - -class SimpleDate(GregorianCalendar): - def __init__(self): - pass - - def getDate(): - return self.getTime() - - def decrease(self,howMuch,unit="m"): - pass - - def getMessageDate(msg): - """ - Return the date of the message - - @param msg analyzed message - @return GregorianCalendar of the messages date - @throws MessagingException - """ - dateMS = msg.getReceivedDate().getTime()//1000 - dateStruct = date.fromtimestamp(dateMS) - return dateStruct - -class ArchivedFolder(object): - def __init__(self,store,name): - self.folder = store.store.getDefaultFolder().getFolder(name) - self.folder.open(Folder.READ_WRITE) - - def purgeOld(self,dateLimit): - toBeDeleted = [] - for msg in self.folder.getMessages(): - flags = msg.getFlags() - if (__getMessageDate(msg) < dateLimit) and (flags.contains(Flags.Flag.SEEN)): - toBeDeleted.append(msg) - self.folder.setFlags(toBeDeleted,Flags.Flag.DELETED, true) - self.folder.expunge() - -class ArchivedStore(object): - """ - >>> myStore = ArchivedStore(paramServer="zimbra") - >>> folderList = myStore.store.getDefaultFolder().list("*") - >>> len(folderList)>0 - 1 - >>> myStore.store.close() - - and - >>> myStore = ArchivedStore(paramServer="zimbra") - >>> folder = ArchivedFolder(myStore,"INBOX/bugzilla/xgl") - >>> folder.folder.getMessageCount() > 0 - 1 - >>> myStore.store.close() - - """ - def __init__(self,paramServer="localhost",paramUser="",paramPassword="",maxageMonth=3): - self.props = System.getProperties() - self.session = Session.getInstance(self.props,None) - self.props.setProperty("javax.net.ssl.keyStore", "/home/matej/.keystore") - self.props.setProperty("javax.net.ssl.trustStore", "/home/matej/.keystore") - if debug: - self.session.setDebug(True) - try: - self.store = self.session.getStore("imaps") - except: - print >> sys.stderr, "Cannot get Store" - raise - - conffile = os.path.expanduser("~/.bugzillarc") - if paramServer: - config = ConfigParser.ConfigParser() - config.read([conffile]) - user,host,port,password = self.props.getProperty("user.name"),\ - "localhost",993,"" - - if config: - if config.has_section(paramServer): - if config.has_option(paramServer, "name"): - user = config.get(paramServer, "name") - if config.has_option(paramServer, "host"): - host = config.get(paramServer, "host") - if config.has_option(paramServer, "port"): - port = config.get(paramServer, "port") - if config.has_option(paramServer, "password"): - password = config.get(paramServer, "password") - - if paramUser: - user=paramUser - if paramPassword: - password=paramPassword - - if debug: - print >>sys.stderr,"host = %s, user = %s, password = %s" % \ - (host,user,password) - - self.__login(host,user,password) - - def __login(self,server,user,password): - try: - self.store.connect(server,user,password) - except: - print >> sys.stderr, "Cannot connect to %s as %s with password %s" %\ - (server,user,password) - raise - -def main(): - """ - >>> threeMonthAgo = date.today() - >>> JD3MAgo = GregorianCalendar(threeMonthAgo.year, - threeMonthAgo.month-1, - threeMonthAgo.day,0,0) - >>> formatter = SimpleDateFormat("yyyy-MM-dd",Locale.US); - >>> JD3MAgoStr = formatter.format(JD3MAgo.getTime()) - >>> str(threeMonthAgo)==JD3MAgoStr - 1 - """ - threeMonthAgo = date.today() - newmonth = threeMonthAgo.month-3 - threeMonthAgo = threeMonthAgo.replace(month=newmonth) - JD3MAgo = GregorianCalendar(threeMonthAgo.year, - threeMonthAgo.month-1, - threeMonthAgo.day,0,0).getTime() - - myStore = ArchivedStore(paramServer="zimbra") - folder = ArchivedFolder(myStore,"INBOX/bugzilla/xgl") - - unreadTerm = FlagTerm(Flags(Flags.Flag.SEEN),True) - dateTerm = ReceivedDateTerm(ComparisonTerm.LT,JD3MAgo) - searchTerm = AndTerm(unreadTerm,dateTerm) - msgsFound = folder.folder.search(searchTerm) - - print len(msgsFound) - myStore.store.close() - -if __name__=='__main__': - main() diff --git a/previousAttempts/jython/purgeObsoleteTest.py b/previousAttempts/jython/purgeObsoleteTest.py deleted file mode 100644 index c4d1ec9..0000000 --- a/previousAttempts/jython/purgeObsoleteTest.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import division -import unittest - -class SimpleDateTest(unittest.TestCase): - def setUp(self): - from purgeObsolete import SimpleDate - - def runInnerTest(self): - threeMonthAgo = date.today() - JD3MAgo = GregorianCalendar(threeMonthAgo.year, - threeMonthAgo.month-1, - threeMonthAgo.day,0,0) - formatter = SimpleDateFormat("yyyy-MM-dd",Locale.US); - JD3MAgoStr = formatter.format(JD3MAgo.getTime()) - self.assertEqual(str(threeMonthAgo),JD3MAgoStr) - - def runTest(self): - pass - -class ArchivedStoreTest(unittest.TestCase): - def setUp(self): - from purgeObsolete import ArchivedStore - self.store = ArchivedStore(paramServer="zimbra") - - def tearDown(self): - self.store.store.close() - - def testConnect(self): - folderList = self.store.store.getDefaultFolder().list("*") - self.assertEqual(len(folderList)>0,True) - - def testOpeningFolder(self): - from purgeObsolete import ArchivedFolder - folder = ArchivedFolder(self.store,"INBOX/bugzilla/xgl") - self.assertEqual(folder.folder.getMessageCount() > 0,True) - - def runTest(self): - self.testConnect() - self.testOpeningFolder() - -if __name__=="__main__": - unittest.main() diff --git a/standards/rfc2177.txt b/standards/rfc2177.txt deleted file mode 100644 index c11c765..0000000 --- a/standards/rfc2177.txt +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - -Network Working Group B. Leiba -Request for Comments: 2177 IBM T.J. Watson Research Center -Category: Standards Track June 1997 - - - IMAP4 IDLE command - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -1. Abstract - - The Internet Message Access Protocol [IMAP4] requires a client to - poll the server for changes to the selected mailbox (new mail, - deletions). It's often more desirable to have the server transmit - updates to the client in real time. This allows a user to see new - mail immediately. It also helps some real-time applications based on - IMAP, which might otherwise need to poll extremely often (such as - every few seconds). (While the spec actually does allow a server to - push EXISTS responses aysynchronously, a client can't expect this - behaviour and must poll.) - - This document specifies the syntax of an IDLE command, which will - allow a client to tell the server that it's ready to accept such - real-time updates. - -2. Conventions Used in this Document - - In examples, "C:" and "S:" indicate lines sent by the client and - server respectively. - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as described in RFC 2060 - [IMAP4]. - -3. Specification - - IDLE Command - - Arguments: none - - Responses: continuation data will be requested; the client sends - the continuation data "DONE" to end the command - - - -Leiba Standards Track [Page 1] - -RFC 2177 IMAP4 IDLE command June 1997 - - - - Result: OK - IDLE completed after client sent "DONE" - NO - failure: the server will not allow the IDLE - command at this time - BAD - command unknown or arguments invalid - - The IDLE command may be used with any IMAP4 server implementation - that returns "IDLE" as one of the supported capabilities to the - CAPABILITY command. If the server does not advertise the IDLE - capability, the client MUST NOT use the IDLE command and must poll - for mailbox updates. In particular, the client MUST continue to be - able to accept unsolicited untagged responses to ANY command, as - specified in the base IMAP specification. - - The IDLE command is sent from the client to the server when the - client is ready to accept unsolicited mailbox update messages. The - server requests a response to the IDLE command using the continuation - ("+") response. The IDLE command remains active until the client - responds to the continuation, and as long as an IDLE command is - active, the server is now free to send untagged EXISTS, EXPUNGE, and - other messages at any time. - - The IDLE command is terminated by the receipt of a "DONE" - continuation from the client; such response satisfies the server's - continuation request. At that point, the server MAY send any - remaining queued untagged responses and then MUST immediately send - the tagged response to the IDLE command and prepare to process other - commands. As in the base specification, the processing of any new - command may cause the sending of unsolicited untagged responses, - subject to the ambiguity limitations. The client MUST NOT send a - command while the server is waiting for the DONE, since the server - will not be able to distinguish a command from a continuation. - - The server MAY consider a client inactive if it has an IDLE command - running, and if such a server has an inactivity timeout it MAY log - the client off implicitly at the end of its timeout period. Because - of that, clients using IDLE are advised to terminate the IDLE and - re-issue it at least every 29 minutes to avoid being logged off. - This still allows a client to receive immediate mailbox updates even - though it need only "poll" at half hour intervals. - - - - - - - - - - - -Leiba Standards Track [Page 2] - -RFC 2177 IMAP4 IDLE command June 1997 - - - Example: C: A001 SELECT INBOX - S: * FLAGS (Deleted Seen) - S: * 3 EXISTS - S: * 0 RECENT - S: * OK [UIDVALIDITY 1] - S: A001 OK SELECT completed - C: A002 IDLE - S: + idling - ...time passes; new mail arrives... - S: * 4 EXISTS - C: DONE - S: A002 OK IDLE terminated - ...another client expunges message 2 now... - C: A003 FETCH 4 ALL - S: * 4 FETCH (...) - S: A003 OK FETCH completed - C: A004 IDLE - S: * 2 EXPUNGE - S: * 3 EXISTS - S: + idling - ...time passes; another client expunges message 3... - S: * 3 EXPUNGE - S: * 2 EXISTS - ...time passes; new mail arrives... - S: * 3 EXISTS - C: DONE - S: A004 OK IDLE terminated - C: A005 FETCH 3 ALL - S: * 3 FETCH (...) - S: A005 OK FETCH completed - C: A006 IDLE - -4. Formal Syntax - - The following syntax specification uses the augmented Backus-Naur - Form (BNF) notation as specified in [RFC-822] as modified by [IMAP4]. - Non-terminals referenced but not defined below are as defined by - [IMAP4]. - - command_auth ::= append / create / delete / examine / list / lsub / - rename / select / status / subscribe / unsubscribe - / idle - ;; Valid only in Authenticated or Selected state - - idle ::= "IDLE" CRLF "DONE" - - - - - - -Leiba Standards Track [Page 3] - -RFC 2177 IMAP4 IDLE command June 1997 - - -5. References - - [IMAP4] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - -6. Security Considerations - - There are no known security issues with this extension. - -7. Author's Address - - Barry Leiba - IBM T.J. Watson Research Center - 30 Saw Mill River Road - Hawthorne, NY 10532 - - Email: leiba@watson.ibm.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leiba Standards Track [Page 4] - diff --git a/standards/rfc4315.txt b/standards/rfc4315.txt new file mode 100644 index 0000000..c026f42 --- /dev/null +++ b/standards/rfc4315.txt @@ -0,0 +1,451 @@ + + + + + + +Network Working Group M. Crispin +Request for Comments: 4315 December 2005 +Obsoletes: 2359 +Category: Standards Track + + + Internet Message Access Protocol (IMAP) - UIDPLUS extension + +Status of This Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2005). + +Abstract + + The UIDPLUS extension of the Internet Message Access Protocol (IMAP) + provides a set of features intended to reduce the amount of time and + resources used by some client operations. The features in UIDPLUS + are primarily intended for disconnected-use clients. + +1. Introduction and Overview + + The UIDPLUS extension is present in any IMAP server implementation + that returns "UIDPLUS" as one of the supported capabilities to the + CAPABILITY command. + + The UIDPLUS extension defines an additional command. In addition, + this document recommends new status response codes in IMAP that + SHOULD be returned by all server implementations, regardless of + whether or not the UIDPLUS extension is implemented. + + The added facilities of the features in UIDPLUS are optimizations; + clients can provide equivalent functionality, albeit less + efficiently, by using facilities in the base protocol. + +1.1. Conventions Used in This Document + + In examples, "C:" and "S:" indicate lines sent by the client and + server, respectively. + + + + + +Crispin Standards Track [Page 1] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "MAY", and "OPTIONAL" in this document are to + be interpreted as described in [KEYWORDS]. + + A "UID set" is similar to the [IMAP] sequence set; however, the "*" + value for a sequence number is not permitted. + +2. Additional Commands + + The following command definition is an extension to [IMAP] section + 6.4. + +2.1. UID EXPUNGE Command + + Arguments: sequence set + + Data: untagged responses: EXPUNGE + + Result: OK - expunge completed + NO - expunge failure (e.g., permission denied) + BAD - command unknown or arguments invalid + + The UID EXPUNGE command permanently removes all messages that both + have the \Deleted flag set and have a UID that is included in the + specified sequence set from the currently selected mailbox. If a + message either does not have the \Deleted flag set or has a UID + that is not included in the specified sequence set, it is not + affected. + + This command is particularly useful for disconnected use clients. + By using UID EXPUNGE instead of EXPUNGE when resynchronizing with + the server, the client can ensure that it does not inadvertantly + remove any messages that have been marked as \Deleted by other + clients between the time that the client was last connected and + the time the client resynchronizes. + + If the server does not support the UIDPLUS capability, the client + should fall back to using the STORE command to temporarily remove + the \Deleted flag from messages it does not want to remove, then + issuing the EXPUNGE command. Finally, the client should use the + STORE command to restore the \Deleted flag on the messages in + which it was temporarily removed. + + Alternatively, the client may fall back to using just the EXPUNGE + command, risking the unintended removal of some messages. + + + + + + +Crispin Standards Track [Page 2] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + + Example: C: A003 UID EXPUNGE 3000:3002 + S: * 3 EXPUNGE + S: * 3 EXPUNGE + S: * 3 EXPUNGE + S: A003 OK UID EXPUNGE completed + +3. Additional Response Codes + + The following response codes are extensions to the response codes + defined in [IMAP] section 7.1. With limited exceptions, discussed + below, server implementations that advertise the UIDPLUS extension + SHOULD return these response codes. + + In the case of a mailbox that has permissions set so that the client + can COPY or APPEND to the mailbox, but not SELECT or EXAMINE it, the + server SHOULD NOT send an APPENDUID or COPYUID response code as it + would disclose information about the mailbox. + + In the case of a mailbox that has UIDNOTSTICKY status (as defined + below), the server MAY omit the APPENDUID or COPYUID response code as + it is not meaningful. + + If the server does not return the APPENDUID or COPYUID response + codes, the client can discover this information by selecting the + destination mailbox. The location of messages placed in the + destination mailbox by COPY or APPEND can be determined by using + FETCH and/or SEARCH commands (e.g., for Message-ID or some unique + marker placed in the message in an APPEND). + + APPENDUID + + Followed by the UIDVALIDITY of the destination mailbox and the UID + assigned to the appended message in the destination mailbox, + indicates that the message has been appended to the destination + mailbox with that UID. + + If the server also supports the [MULTIAPPEND] extension, and if + multiple messages were appended in the APPEND command, then the + second value is a UID set containing the UIDs assigned to the + appended messages, in the order they were transmitted in the + APPEND command. This UID set may not contain extraneous UIDs or + the symbol "*". + + Note: the UID set form of the APPENDUID response code MUST NOT + be used if only a single message was appended. In particular, + a server MUST NOT send a range such as 123:123. This is + because a client that does not support [MULTIAPPEND] expects + only a single UID and not a UID set. + + + +Crispin Standards Track [Page 3] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + + UIDs are assigned in strictly ascending order in the mailbox + (refer to [IMAP], section 2.3.1.1) and UID ranges are as in + [IMAP]; in particular, note that a range of 12:10 is exactly + equivalent to 10:12 and refers to the sequence 10,11,12. + + This response code is returned in a tagged OK response to the + APPEND command. + + COPYUID + + Followed by the UIDVALIDITY of the destination mailbox, a UID set + containing the UIDs of the message(s) in the source mailbox that + were copied to the destination mailbox and containing the UIDs + assigned to the copied message(s) in the destination mailbox, + indicates that the message(s) have been copied to the destination + mailbox with the stated UID(s). + + The source UID set is in the order the message(s) were copied; the + destination UID set corresponds to the source UID set and is in + the same order. Neither of the UID sets may contain extraneous + UIDs or the symbol "*". + + UIDs are assigned in strictly ascending order in the mailbox + (refer to [IMAP], section 2.3.1.1) and UID ranges are as in + [IMAP]; in particular, note that a range of 12:10 is exactly + equivalent to 10:12 and refers to the sequence 10,11,12. + + This response code is returned in a tagged OK response to the COPY + command. + + UIDNOTSTICKY + + The selected mailbox is supported by a mail store that does not + support persistent UIDs; that is, UIDVALIDITY will be different + each time the mailbox is selected. Consequently, APPEND or COPY + to this mailbox will not return an APPENDUID or COPYUID response + code. + + This response code is returned in an untagged NO response to the + SELECT command. + + Note: servers SHOULD NOT have any UIDNOTSTICKY mail stores. + This facility exists to support legacy mail stores in which it + is technically infeasible to support persistent UIDs. This + should be avoided when designing new mail stores. + + + + + + +Crispin Standards Track [Page 4] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + + Example: C: A003 APPEND saved-messages (\Seen) {297} + C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) + C: From: Fred Foobar <foobar@example.com> + C: Subject: afternoon meeting + C: To: mooch@example.com + C: Message-Id: <B27397-0100000@example.com> + C: MIME-Version: 1.0 + C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII + C: + C: Hello Joe, do you think we can meet at 3:30 tomorrow? + C: + S: A003 OK [APPENDUID 38505 3955] APPEND completed + C: A004 COPY 2:4 meeting + S: A004 OK [COPYUID 38505 304,319:320 3956:3958] Done + C: A005 UID COPY 305:310 meeting + S: A005 OK No matching messages, so nothing copied + C: A006 COPY 2 funny + S: A006 OK Done + C: A007 SELECT funny + S: * 1 EXISTS + S: * 1 RECENT + S: * OK [UNSEEN 1] Message 1 is first unseen + S: * OK [UIDVALIDITY 3857529045] Validity session-only + S: * OK [UIDNEXT 2] Predicted next UID + S: * NO [UIDNOTSTICKY] Non-persistent UIDs + S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) + S: * OK [PERMANENTFLAGS (\Deleted \Seen)] Limited + S: A007 OK [READ-WRITE] SELECT completed + + In this example, A003 and A004 demonstrate successful appending and + copying to a mailbox that returns the UIDs assigned to the messages. + A005 is an example in which no messages were copied; this is because + in A003, we see that message 2 had UID 304, and message 3 had UID + 319; therefore, UIDs 305 through 310 do not exist (refer to section + 2.3.1.1 of [IMAP] for further explanation). A006 is an example of a + message being copied that did not return a COPYUID; and, as expected, + A007 shows that the mail store containing that mailbox does not + support persistent UIDs. + +4. Formal Syntax + + Formal syntax is defined using ABNF [ABNF], which extends the ABNF + rules defined in [IMAP]. The IMAP4 ABNF should be imported before + attempting to validate these rules. + + append-uid = uniqueid + + capability =/ "UIDPLUS" + + + +Crispin Standards Track [Page 5] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + + command-select =/ uid-expunge + + resp-code-apnd = "APPENDUID" SP nz-number SP append-uid + + resp-code-copy = "COPYUID" SP nz-number SP uid-set SP uid-set + + resp-text-code =/ resp-code-apnd / resp-code-copy / "UIDNOTSTICKY" + ; incorporated before the expansion rule of + ; atom [SP 1*<any TEXT-CHAR except "]">] + ; that appears in [IMAP] + + uid-expunge = "UID" SP "EXPUNGE" SP sequence-set + + uid-set = (uniqueid / uid-range) *("," uid-set) + + uid-range = (uniqueid ":" uniqueid) + ; two uniqueid values and all values + ; between these two regards of order. + ; Example: 2:4 and 4:2 are equivalent. + + Servers that support [MULTIAPPEND] will have the following extension + to the above rules: + + append-uid =/ uid-set + ; only permitted if client uses [MULTIAPPEND] + ; to append multiple messages. + +5. Security Considerations + + The COPYUID and APPENDUID response codes return information about the + mailbox, which may be considered sensitive if the mailbox has + permissions set that permit the client to COPY or APPEND to the + mailbox, but not SELECT or EXAMINE it. + + Consequently, these response codes SHOULD NOT be issued if the client + does not have access to SELECT or EXAMINE the mailbox. + +6. IANA Considerations + + This document constitutes registration of the UIDPLUS capability in + the imap4-capabilities registry, replacing [RFC2359]. + +7. Normative References + + [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax + Specifications: ABNF", RFC 4234, October 2005. + + + + + +Crispin Standards Track [Page 6] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + + [IMAP] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - + VERSION 4rev1", RFC 3501, March 2003. + + [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [MULTIAPPEND] Crispin, M., "Internet Message Access Protocol (IMAP) - + MULTIAPPEND Extension", RFC 3502, March 2003. + +8. Informative References + + [RFC2359] Myers, J., "IMAP4 UIDPLUS extension", RFC 2359, June + 1998. + +9. Changes from RFC 2359 + + This document obsoletes [RFC2359]. However, it is based upon that + document, and takes substantial text from it (albeit with numerous + clarifications in wording). + + [RFC2359] implied that a server must always return COPYUID/APPENDUID + data; thus suggesting that in such cases the server should return + arbitrary data if the destination mailbox did not support persistent + UIDs. This document adds the UIDNOTSTICKY response code to indicate + that a mailbox does not support persistent UIDs, and stipulates that + a UIDPLUS server does not return COPYUID/APPENDUID data when the COPY + (or APPEND) destination mailbox has UIDNOTSTICKY status. + +Author's Address + + Mark R. Crispin + Networks and Distributed Computing + University of Washington + 4545 15th Avenue NE + Seattle, WA 98105-4527 + + Phone: (206) 543-5762 + EMail: MRC@CAC.Washington.EDU + + + + + + + + + + + + + +Crispin Standards Track [Page 7] + +RFC 4315 IMAP - UIDPLUS Extension December 2005 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at ietf- + ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + +Crispin Standards Track [Page 8] + diff --git a/standards/rfc6851.txt b/standards/rfc6851.txt new file mode 100644 index 0000000..a82331a --- /dev/null +++ b/standards/rfc6851.txt @@ -0,0 +1,451 @@ + + + + + + +Internet Engineering Task Force (IETF) A. Gulbrandsen +Request for Comments: 6851 +Category: Standards Track N. Freed, Ed. +ISSN: 2070-1721 Oracle + January 2013 + + + Internet Message Access Protocol (IMAP) - MOVE Extension + +Abstract + + This document defines an IMAP extension consisting of two new + commands, MOVE and UID MOVE, that are used to move messages from one + mailbox to another. + +Status of This Memo + + This is an Internet Standards Track document. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Further information on + Internet Standards is available in Section 2 of RFC 5741. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + http://www.rfc-editor.org/info/rfc6851. + +Copyright Notice + + Copyright (c) 2013 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + + + + + + + + +Gulbrandsen & Freed Standards Track [Page 1] + +RFC 6851 IMAP - MOVE Extension January 2013 + + +1. Introduction + + This document defines an IMAP [RFC3501] extension to facilitate + moving messages from one mailbox to another. This is accomplished by + defining a new MOVE command and extending the UID command to allow + UID MOVE. + + A move function is not provided in the base IMAP specification, so + clients have instead had to use a combination of the COPY, STORE, and + EXPUNGE commands to perform this very common operation. + + Implementors have long pointed out some shortcomings with this + approach. Because the moving of a message is not an atomic process, + interruptions can leave messages in intermediate states. Because + multiple clients can be accessing the mailboxes at the same time, + clients can see messages in intermediate states even without + interruptions. If the source mailbox contains other messages that + are flagged for deletion, the third step can have the side effect of + expunging more than just the set of moved messages. Additionally, + servers with certain types of back-end message stores might have + efficient ways of moving messages, which don't involve the actual + copying of data. Such efficiencies are often not available to the + COPY/STORE/EXPUNGE process. + + The MOVE extension is present in any IMAP implementation that returns + "MOVE" as one of the supported capabilities to the CAPABILITY + command. + +2. Conventions Used in This Document + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in [RFC2119]. + + Formal syntax is specified using ABNF [RFC5234]. + + Example lines prefaced by "C:" are sent by the client and ones + prefaced by "S:" by the server. + + + + + + + + + + + + + +Gulbrandsen & Freed Standards Track [Page 2] + +RFC 6851 IMAP - MOVE Extension January 2013 + + +3. MOVE and UID MOVE + +3.1. MOVE Command + + Arguments: sequence set + mailbox name + + Responses: no specific responses for this command + + Result: OK - move completed + + NO - move error: can't move those messages or to that name + + BAD - command unknown or arguments invalid + +3.2. UID MOVE Command + + This extends the first form of the UID command (see [RFC3501], + Section 6.4.8) to add the MOVE command defined above as a valid + argument. + +3.3. Semantics of MOVE and UID MOVE + + The MOVE command takes two arguments: a message set (sequence numbers + for MOVE, UIDs for UID MOVE) and a named mailbox. Each message + included in the set is moved, rather than copied, from the selected + (source) mailbox to the named (target) mailbox. + + This means that a new message is created in the target mailbox with a + new UID, the original message is removed from the source mailbox, and + it appears to the client as a single action. This has the same + effect for each message as this sequence: + + 1. [UID] COPY + + 2. [UID] STORE +FLAGS.SILENT \DELETED + + 3. UID EXPUNGE + + Although the effect of the MOVE is the same as the preceding steps, + the semantics are not identical: The intermediate states produced by + those steps do not occur, and the response codes are different. In + particular, though the COPY and EXPUNGE response codes will be + returned, response codes for a STORE MUST NOT be generated and the + \DELETED flag MUST NOT be set for any message. + + + + + + +Gulbrandsen & Freed Standards Track [Page 3] + +RFC 6851 IMAP - MOVE Extension January 2013 + + + Because a MOVE applies to a set of messages, it might fail partway + through the set. Regardless of whether the command is successful in + moving the entire set, each individual message SHOULD either be moved + or unaffected. The server MUST leave each message in a state where + it is in at least one of the source or target mailboxes (no message + can be lost or orphaned). The server SHOULD NOT leave any message in + both mailboxes (it would be bad for a partial failure to result in a + bunch of duplicate messages). This is true even if the server + returns a tagged NO response to the command. + + Because of the similarity of MOVE to COPY, extensions that affect + COPY affect MOVE in the same way. Response codes such as TRYCREATE + (see [RFC3501], Section 6.4.7), as well as those defined by + extensions, are sent as appropriate. See Section 4 for more + information about how MOVE interacts with other IMAP extensions. + + An example: + + C: a UID MOVE 42:69 foo + S: * OK [COPYUID 432432 42:69 1202:1229] + S: * 22 EXPUNGE + S: (more expunges) + S: a OK Done + + Note that the server may send unrelated EXPUNGE responses as well, if + any happen to have been expunged at the same time; this is normal + IMAP operation. + + Implementers will need to read [RFC4315] to understand what UID + EXPUNGE does, though full implementation of [RFC4315] is not + necessary. + + Note that moving a message to the currently selected mailbox (that + is, where the source and target mailboxes are the same) is allowed + when copying the message to the currently selected mailbox is + allowed. + + The server may send EXPUNGE (or VANISHED) responses before the tagged + response, so the client cannot safely send more commands with message + sequence number arguments while the server is processing MOVE or UID + MOVE. + + Both MOVE and UID MOVE can be pipelined with other commands, but care + has to be taken. Both commands modify sequence numbers and also + allow unrelated EXPUNGE responses. The renumbering of other messages + in the source mailbox following any EXPUNGE response can be + surprising and makes it unsafe to pipeline any command that relies on + message sequence numbers after a MOVE or UID MOVE. Similarly, MOVE + + + +Gulbrandsen & Freed Standards Track [Page 4] + +RFC 6851 IMAP - MOVE Extension January 2013 + + + cannot be pipelined with a command that might cause message + renumbering. See [RFC3501], Section 5.5, for more information about + ambiguities as well as handling requirements for both clients and + servers. + +4. Interaction with Other Extensions + + This section describes how MOVE interacts with some other IMAP + extensions. + +4.1. RFC 2087, QUOTA + + The QUOTA extension (defined by [RFC2087]) may interact with MOVE on + some servers, in the sense that a MOVE command may succeed where COPY + would cause a quota overrun. + +4.2. RFC 4314, Access Control List (ACL) + + The ACL rights [RFC4314] required for MOVE and UID MOVE are the union + of the ACL rights required for UID STORE, UID COPY, and UID EXPUNGE. + +4.3. RFC 4315, UIDPLUS + + Servers supporting UIDPLUS [RFC4315] SHOULD send COPYUID in response + to a UID MOVE command. For additional information see Section 3 of + [RFC4315]. + + Servers implementing UIDPLUS are also advised to send the COPYUID + response code in an untagged OK before sending EXPUNGE or moved + responses. (Sending COPYUID in the tagged OK, as described in the + UIDPLUS specification, means that clients first receive an EXPUNGE + for a message and afterwards COPYUID for the same message. It can be + unnecessarily difficult to process that sequence usefully.) + +4.4. RFC 5162, QRESYNC + + The QRESYNC extension [RFC5162] states that the server SHOULD send + VANISHED rather than EXPUNGE in response to the UID EXPUNGE command. + The same requirement applies to MOVE, and a QRESYNC-enabled client + needs to handle both VANISHED and EXPUNGE responses to a UID MOVE + command. + + If the server is capable of storing modification sequences for the + selected mailbox, it MUST increment the per-mailbox mod-sequence if + at least one message was permanently moved due to the execution of + the MOVE/UID MOVE command. For each permanently removed message, the + server MUST remember the incremented mod-sequence and corresponding + UID. If at least one message was moved, the server MUST send the + + + +Gulbrandsen & Freed Standards Track [Page 5] + +RFC 6851 IMAP - MOVE Extension January 2013 + + + updated per-mailbox modification sequence using the HIGHESTMODSEQ + response code (defined in [RFC4551]) in the tagged or untagged OK + response. + + When one or more messages are moved to a target mailbox, if the + server is capable of storing modification sequences for the mailbox, + the server MUST generate and assign new modification sequence numbers + to the moved messages that are higher than the highest modification + sequence of the messages originally in the mailbox. + +4.5. IMAP Events in Sieve + + MOVE applies to IMAP events in Sieve [RFC6785] in the same way as + COPY does. Therefore, MOVE can cause a Sieve script to be invoked + with the imap.cause set to "COPY". Because MOVE does not cause flags + to be changed, a MOVE command will not result in a script invocation + with the imap.cause set to "FLAG". + +5. Formal Syntax + + The following syntax specification uses the Augmented Backus-Naur + Form (ABNF) notation as specified in [RFC5234]. [RFC3501] defines + the non-terminals "capability", "command-select", "sequence-set", and + "mailbox". + + Except as noted otherwise, all alphabetic characters are case + insensitive. The use of upper or lower case characters to define + token strings is for editorial clarity only. Implementations MUST + accept these strings in a case-insensitive fashion. + + capability =/ "MOVE" + + command-select =/ move + move = "MOVE" SP sequence-set SP mailbox + uid = "UID" SP (copy / fetch / search / store / move) + +6. Security Considerations + + MOVE does not introduce any new capabilities to IMAP, and this limits + the security impact. However, the transactional semantics of MOVE + may interact with specific implementations in ways that could have + unexpected consequences. For example, moving messages between + mailboxes under the quota root may require temporary suspension of + quota checking. + + An additional area of concern is interaction with antispam, + antivirus, and other security scanning and auditing mechanisms. + Different mailboxes may have different security policies that could + + + +Gulbrandsen & Freed Standards Track [Page 6] + +RFC 6851 IMAP - MOVE Extension January 2013 + + + interact with MOVE in complex ways. Scanning with updated rules may + also be required when messages are moved even when the underlying + policy has not changed. + + MOVE does relieve a problem with the base specification, since client + authors currently have to devise and implement complicated algorithms + to handle partial failures of the STORE/COPY/EXPUNGE trio. + Incomplete or improper implementation of these algorithms can lead to + mail loss. + +7. IANA Considerations + + The IANA has added MOVE to the "IMAP 4 Capabilities" registry, + <http://www.iana.org/assignments/imap4-capabilities>. + +8. Acknowledgments + + This document is dedicated to the memory of Mark Crispin, the + inventor of the IMAP protocol, author of the IMAP protocol + specification [RFC3501], and contributor to many other email + specifications in the IETF. + + An extension like this has been proposed many times, by many people. + This document is based on several of those proposals, most recently + that by Witold Krecicki. Witold, Benoit Claise, Adrien W. de Croy, + Stephen Farrell, Bron Gondwana, Dan Karp, Christian Ketterer, Murray + Kucherawy, Jan Kundrat, Barry Leiba, Alexey Melnikov, Kathleen + Moriarty, Zoltan Ordogh, Pete Resnick, Timo Sirainen, Michael + Slusarz, and others provided valuable comments. + +9. References + +9.1. Normative References + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC3501] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION + 4rev1", RFC 3501, March 2003. + + [RFC4314] Melnikov, A., "IMAP4 Access Control List (ACL) Extension", + RFC 4314, December 2005. + + [RFC4315] Crispin, M., "Internet Message Access Protocol (IMAP) - + UIDPLUS extension", RFC 4315, December 2005. + + + + + + +Gulbrandsen & Freed Standards Track [Page 7] + +RFC 6851 IMAP - MOVE Extension January 2013 + + + [RFC4551] Melnikov, A. and S. Hole, "IMAP Extension for Conditional + STORE Operation or Quick Flag Changes Resynchronization", + RFC 4551, June 2006. + + [RFC5162] Melnikov, A., Cridland, D., and C. Wilson, "IMAP4 + Extensions for Quick Mailbox Resynchronization", RFC 5162, + March 2008. + + [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax + Specifications: ABNF", STD 68, RFC 5234, January 2008. + +9.2. Informative References + + [RFC2087] Myers, J., "IMAP4 QUOTA extension", RFC 2087, + January 1997. + + [RFC6785] Leiba, B., "Support for Internet Message Access Protocol + (IMAP) Events in Sieve", RFC 6785, November 2012. + +Authors' Addresses + + Arnt Gulbrandsen + Schweppermannstr. 8 + D-81671 Muenchen + Germany + + Fax: +49 89 4502 9758 + EMail: arnt@gulbrandsen.priv.no + + + Ned Freed (editor) + Oracle + 800 Royal Oaks + Monrovia, CA 91016-6347 + USA + + EMail: ned+ietf@mrochek.com + + + + + + + + + + + + + + +Gulbrandsen & Freed Standards Track [Page 8] + |