Compare commits
32 Commits
Author | SHA1 | Date |
---|---|---|
Nikolaus Schulz | e1a6028332 | |
Nikolaus Schulz | 4346bc5815 | |
Nikolaus Schulz | e3f0440305 | |
Nikolaus Schulz | 22d4393cb6 | |
Nikolaus Schulz | 09e460555e | |
Nikolaus Schulz | 87084b69f0 | |
Nikolaus Schulz | e3f5289e13 | |
Nikolaus Schulz | 483a58879f | |
Nikolaus Schulz | 1fa57aa577 | |
Nikolaus Schulz | 6cb9ba9122 | |
Nikolaus Schulz | 14e0929ba2 | |
Nikolaus Schulz | 14e5cd6eb1 | |
Nikolaus Schulz | eb07611fae | |
Nikolaus Schulz | f9f9eacd88 | |
Nikolaus Schulz | 947be25f82 | |
Nikolaus Schulz | 88653766db | |
Nikolaus Schulz | 6b0fefc45f | |
Nikolaus Schulz | f6046b9d69 | |
Nikolaus Schulz | 39e6a532d0 | |
Nikolaus Schulz | 8173caa81d | |
Nikolaus Schulz | 4f8171341d | |
Nikolaus Schulz | 0e1aace796 | |
Nikolaus Schulz | 8190e4807e | |
Nikolaus Schulz | 0437ec3e8b | |
Nikolaus Schulz | c2106bdda1 | |
Nikolaus Schulz | f6be896b1f | |
Nikolaus Schulz | ea0d95e121 | |
Nikolaus Schulz | 7ee2555cc2 | |
Nikolaus Schulz | 393f08bb2e | |
Nikolaus Schulz | ad4c4b9642 | |
Nikolaus Schulz | a08cde18fb | |
Nikolaus Schulz | 77a2856e48 |
|
@ -0,0 +1,3 @@
|
|||
/archivemail.1
|
||||
/archivemail.html
|
||||
/MANIFEST
|
16
CHANGELOG
16
CHANGELOG
|
@ -1,3 +1,19 @@
|
|||
version 0.9.0 - 9 July 2011
|
||||
|
||||
* Fixed manpage installation path to be FHS compliant
|
||||
* Speed up IMAP archiving with the --quiet option
|
||||
* Ported the manpage from SGML to XML
|
||||
* Fix test suite failures with Python 2.7. Closes: #3314293.
|
||||
* IMAP: support international mailbox names containing non-ASCII characters.
|
||||
* IMAP: handle broken servers sending no untagged SEARCH response.
|
||||
Closes: #879716, #3213272.
|
||||
* IMAP: support servers listening on non-standard ports. Closes: #3168416.
|
||||
|
||||
version 0.8.2 - 16 October 2010
|
||||
|
||||
* IMAP: don't prepend NAMESPACE prefix to INBOX and its children.
|
||||
Closes: #3083236.
|
||||
|
||||
version 0.8.1 - 30 September 2010
|
||||
|
||||
* IMAP: fixed handling of LIST replies by the server where the mailbox name
|
||||
|
|
7
FAQ
7
FAQ
|
@ -2,10 +2,9 @@
|
|||
1. Why doesn't archivemail support bzip2 compression in addition to gzip?
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
I am quite happy to add bzip2 support to archivemail as soon as a 'bzip2'
|
||||
module (similar to the gzip module) is available for python.
|
||||
[ Hint hint ;) ]
|
||||
|
||||
The bzip2 module in Python 2.x is not fully compatible with the gzip module,
|
||||
and cannot be used with the current implementation of compressed mailbox
|
||||
support in archivemail. See Python feature request #5863 for details.
|
||||
|
||||
2. Can you add a switch to archive mailboxes greater than a certain size?
|
||||
-------------------------------------------------------------------------
|
||||
|
|
|
@ -5,6 +5,7 @@ include MANIFEST
|
|||
include TODO
|
||||
include NEWS
|
||||
include archivemail.1
|
||||
include archivemail.sgml
|
||||
include archivemail.xml
|
||||
include db2man.xsl
|
||||
graft examples
|
||||
include test_archivemail
|
||||
|
|
23
Makefile
23
Makefile
|
@ -1,4 +1,3 @@
|
|||
|
||||
VERSION=$(shell python setup.py --version)
|
||||
VERSION_TAG=v$(subst .,_,$(VERSION))
|
||||
TARFILE=archivemail-$(VERSION).tar.gz
|
||||
|
@ -8,7 +7,6 @@ default:
|
|||
@echo "no default target"
|
||||
|
||||
clean:
|
||||
rm -f manpage.links manpage.refs manpage.log
|
||||
rm -rf $(HTDOCS)
|
||||
|
||||
test:
|
||||
|
@ -22,17 +20,9 @@ clobber: clean
|
|||
sdist: clobber doc
|
||||
python setup.py sdist
|
||||
|
||||
# FIXME: bdist_rpm chokes on the manpage.
|
||||
# This is python/distutils bug #644744
|
||||
#bdist_rpm: clobber doc
|
||||
# python setup.py bdist_rpm
|
||||
|
||||
tag:
|
||||
git tag -a $(VERSION_TAG)
|
||||
|
||||
upload:
|
||||
(cd dist && lftp -c 'open upload.sf.net && cd incoming && put $(TARFILE)')
|
||||
|
||||
doc: archivemail.1 archivemail.html
|
||||
|
||||
htdocs: $(HTDOCS).tgz
|
||||
|
@ -42,13 +32,12 @@ $(HTDOCS).tgz: index.html archivemail.html RELNOTES style.css manpage.css
|
|||
cd $(HTDOCS) && mv archivemail.html manpage.html
|
||||
tar czf $(HTDOCS).tgz $(HTDOCS)
|
||||
|
||||
archivemail.1: archivemail.sgml
|
||||
docbook2man archivemail.sgml
|
||||
chmod 644 archivemail.1
|
||||
archivemail.1: archivemail.xml db2man.xsl
|
||||
xsltproc db2man.xsl archivemail.xml
|
||||
|
||||
archivemail.html: archivemail.sgml db2html.dsl
|
||||
docbook2html --dsl db2html.dsl -u archivemail.sgml
|
||||
chmod 644 archivemail.html
|
||||
archivemail.html: archivemail.xml db2html.xsl
|
||||
xsltproc --output archivemail.html \
|
||||
db2html.xsl archivemail.xml
|
||||
tidy -modify -indent -f /dev/null archivemail.html || true
|
||||
|
||||
.PHONY: clean test clobber sdist tag upload doc htdocs
|
||||
.PHONY: default clean test clobber sdist tag doc htdocs
|
||||
|
|
5
NEWS
5
NEWS
|
@ -1,3 +1,8 @@
|
|||
Notable changes in archivemail 0.9.0:
|
||||
|
||||
* IMAP: support for international mailbox names containing non-ASCII
|
||||
characters.
|
||||
|
||||
Notable changes in archivemail 0.8.0:
|
||||
|
||||
* Removed the feature to setuid to the mailbox owners when run as root.
|
||||
|
|
177
archivemail
177
archivemail
|
@ -24,11 +24,11 @@ Website: http://archivemail.sourceforge.net/
|
|||
"""
|
||||
|
||||
# global administrivia
|
||||
__version__ = "archivemail v0.8.1"
|
||||
__version__ = "archivemail v0.9.0"
|
||||
__copyright__ = """\
|
||||
Copyright (C) 2002 Paul Rodger <paul@paulrodger.com>
|
||||
(C) 2006 Peter Poeml <poeml@suse.de>,
|
||||
(C) 2006-2010 Nikolaus Schulz <microschulz@web.de>
|
||||
(C) 2006-2011 Nikolaus Schulz <microschulz@web.de>
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."""
|
||||
|
||||
|
@ -68,11 +68,14 @@ import time
|
|||
import urlparse
|
||||
import errno
|
||||
import socket
|
||||
import locale
|
||||
|
||||
# From_ mangling regex.
|
||||
from_re = re.compile(r'^From ', re.MULTILINE)
|
||||
imapsize_re = re.compile(r'^(?P<msn>[0-9]+) \(RFC822\.SIZE (?P<size>[0-9]+)\)')
|
||||
|
||||
userencoding = locale.getpreferredencoding()
|
||||
|
||||
############## class definitions ###############
|
||||
|
||||
class ArchivemailException(Exception):
|
||||
|
@ -195,7 +198,7 @@ class Options:
|
|||
script_name = os.path.basename(sys.argv[0])
|
||||
min_size = None
|
||||
verbose = False
|
||||
debug_imap = False
|
||||
debug_imap = 0
|
||||
warn_duplicates = False
|
||||
copy_old_mail = False
|
||||
archive_all = False
|
||||
|
@ -1287,9 +1290,9 @@ def _archive_imap(mailbox_name):
|
|||
vprint("Setting imaplib.Debug = %d" % options.debug_imap)
|
||||
imaplib.Debug = options.debug_imap
|
||||
archive = None
|
||||
imap_str = mailbox_name[mailbox_name.find('://') + 3:]
|
||||
imap_username, imap_password, imap_server, imap_folder_pattern = \
|
||||
parse_imap_url(imap_str)
|
||||
imap_username, imap_password, \
|
||||
imap_server, imap_server_port, \
|
||||
imap_folder_pattern = parse_imap_url(mailbox_name)
|
||||
if not imap_password:
|
||||
if options.pwfile:
|
||||
imap_password = open(options.pwfile).read().rstrip()
|
||||
|
@ -1300,11 +1303,13 @@ def _archive_imap(mailbox_name):
|
|||
|
||||
is_ssl = mailbox_name[:5].lower() == 'imaps'
|
||||
if is_ssl:
|
||||
vprint("establishing secure connection to server %s" % imap_server)
|
||||
imap_srv = imaplib.IMAP4_SSL(imap_server)
|
||||
vprint("establishing secure connection to server %s, port %s" %
|
||||
(imap_server, imap_server_port))
|
||||
imap_srv = imaplib.IMAP4_SSL(imap_server, imap_server_port)
|
||||
else:
|
||||
vprint("establishing connection to server %s" % imap_server)
|
||||
imap_srv = imaplib.IMAP4(imap_server)
|
||||
vprint("establishing connection to server %s, port %s" %
|
||||
(imap_server, imap_server_port))
|
||||
imap_srv = imaplib.IMAP4(imap_server, imap_server_port)
|
||||
if "AUTH=CRAM-MD5" in imap_srv.capabilities:
|
||||
vprint("authenticating (cram-md5) to server as %s" % imap_username)
|
||||
result, response = imap_srv.login_cram_md5(imap_username, imap_password)
|
||||
|
@ -1345,13 +1350,17 @@ def _archive_imap(mailbox_name):
|
|||
result, response = imap_srv.search(None, imap_filter)
|
||||
if result != 'OK': unexpected_error("imap search failed; server says '%s'" %
|
||||
response[0])
|
||||
# response is a list with a single item, listing message sequence numbers
|
||||
# like ['1 2 3 1016']
|
||||
message_list = response[0].split()
|
||||
if response[0] is not None:
|
||||
# response is a list with a single item, listing message
|
||||
# sequence numbers like ['1 2 3 1016']
|
||||
message_list = response[0].split()
|
||||
else:
|
||||
# Broken server has sent no untagged response; assume empty result set.
|
||||
message_list = []
|
||||
vprint("%d messages are matching filter" % len(message_list))
|
||||
|
||||
# First, gather data for the statistics.
|
||||
if total_msg_count > 0:
|
||||
if total_msg_count > 0 and not options.quiet:
|
||||
vprint("fetching size of messages...")
|
||||
result, response = imap_srv.fetch('1:*', '(RFC822.SIZE)')
|
||||
if result != 'OK': unexpected_error("Failed to fetch message sizes; "
|
||||
|
@ -1410,6 +1419,107 @@ def _archive_imap(mailbox_name):
|
|||
|
||||
############### IMAP functions ###############
|
||||
|
||||
|
||||
# First, some IMAP modified UTF-7 support functions.
|
||||
|
||||
# The modified BASE64 alphabet. 64 characters, each one encodes 6 Bit.
|
||||
mb64alpha = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+,'
|
||||
|
||||
def isprint_ascii(char):
|
||||
"""Test for an ASCII printable character."""
|
||||
return 0x20 <= ord(char) and ord(char) <= 0x7e
|
||||
|
||||
def mod_utf7_encode(ustr):
|
||||
"""Encode unicode string object in modified UTF-7."""
|
||||
|
||||
def mb64_encode(tomb64):
|
||||
"""Encode unicode string object as a modified UTF-7 shifted sequence
|
||||
in modified BASE64."""
|
||||
u16be = tomb64.encode('utf_16_be')
|
||||
mb64 = ""
|
||||
# Process 24-bit blocks, encoding them in 6-bit steps.
|
||||
for block in [u16be[i:i+3] for i in range(0, len(u16be), 3)]:
|
||||
idx = 0
|
||||
shift = 2
|
||||
for octet in block:
|
||||
mb64 += mb64alpha[idx | (ord(octet) >> shift)]
|
||||
idx = (ord(octet) << (6-shift)) & 0x3f
|
||||
shift += 2
|
||||
mb64 += mb64alpha[idx]
|
||||
return mb64
|
||||
|
||||
mu7 = ""
|
||||
tomb64 = u""
|
||||
for c in ustr:
|
||||
if not isprint_ascii(c):
|
||||
tomb64 += c
|
||||
continue
|
||||
if tomb64:
|
||||
mu7 += '&' + mb64_encode(tomb64) + '-'
|
||||
tomb64 = u""
|
||||
if c == '&':
|
||||
mu7 += '&-'
|
||||
else:
|
||||
mu7 += str(c)
|
||||
if tomb64:
|
||||
mu7 += '&' + mb64_encode(tomb64) + '-'
|
||||
return mu7
|
||||
|
||||
def mod_utf7_decode(mu7):
|
||||
"""Decode a modified UTF-7 encoded string to an unicode string object."""
|
||||
|
||||
def mb64_decode(mb64):
|
||||
"""Decode a modified UTF-7 shifted sequence from modified BASE64 to an
|
||||
unicode string object."""
|
||||
if not mb64:
|
||||
# A null shift '&-' decodes to '&'.
|
||||
return u"&"
|
||||
u16be = ""
|
||||
# Process blocks of 4 BASE64 characters, decoding each char to 6 bits.
|
||||
for block in [mb64[i:i+4] for i in range(0, len(mb64), 4)]:
|
||||
carrybits = mb64alpha.index(block[0]) << 2
|
||||
shift = 4
|
||||
for char in block[1:]:
|
||||
bits = mb64alpha.index(char)
|
||||
u16be += chr(carrybits | (bits >> shift))
|
||||
carrybits = (bits << (8-shift)) & 0xff
|
||||
shift -= 2
|
||||
if carrybits:
|
||||
raise ValueError("Ill-formed modified UTF-7 string: "
|
||||
"trailing bits in shifted sequence")
|
||||
return u16be.decode('utf_16_be')
|
||||
|
||||
ustr = u""
|
||||
mb64 = ""
|
||||
inmb64 = False
|
||||
for octet in mu7:
|
||||
if not isprint_ascii(octet):
|
||||
raise ValueError("Ill-formed modified UTF-7 string: "
|
||||
"contains non-printable ASCII" % ord(octet))
|
||||
if not inmb64:
|
||||
if octet == '&':
|
||||
inmb64 = True
|
||||
else:
|
||||
ustr += octet
|
||||
continue
|
||||
|
||||
if octet in mb64alpha:
|
||||
mb64 += octet
|
||||
continue
|
||||
|
||||
if octet == '-':
|
||||
inmb64 = False
|
||||
ustr += mb64_decode(mb64)
|
||||
mb64 = ""
|
||||
else:
|
||||
break # This triggers the exception below.
|
||||
|
||||
if inmb64:
|
||||
raise ValueError("Ill-formed modified UTF-7 string: "
|
||||
"unterminated BASE64 sequence")
|
||||
return ustr
|
||||
|
||||
|
||||
def imap_quote(astring):
|
||||
"""Quote an IMAP `astring' string (see RFC 3501, section "Formal Syntax")."""
|
||||
if astring.startswith('"') and astring.endswith('"'):
|
||||
|
@ -1443,6 +1553,7 @@ def parse_imap_url(url):
|
|||
a, b = string.split(delim, 1)
|
||||
return a, b
|
||||
|
||||
scheme, url = url.split('://')
|
||||
password = None
|
||||
try:
|
||||
if options.pwfile:
|
||||
|
@ -1458,7 +1569,16 @@ def parse_imap_url(url):
|
|||
server, folder = url.split('/', 1)
|
||||
except ValueError:
|
||||
unexpected_error("Invalid IMAP connection string")
|
||||
return username, password, server, folder
|
||||
try:
|
||||
server, port = server.split(':')
|
||||
except ValueError:
|
||||
if scheme.lower() == 'imap':
|
||||
port = 143
|
||||
else:
|
||||
port = 993
|
||||
else:
|
||||
port = int(port)
|
||||
return username, password, server, port, folder
|
||||
|
||||
|
||||
def imap_getdelim(imap_server):
|
||||
|
@ -1520,7 +1640,8 @@ def imap_smart_select(srv, mailbox):
|
|||
vprint("examining imap folder '%s' read-only" % mailbox)
|
||||
else:
|
||||
vprint("selecting imap folder '%s'" % mailbox)
|
||||
result, response = srv.select(imap_quote(mailbox), roflag)
|
||||
imap_mailbox = mod_utf7_encode(mailbox.decode(userencoding))
|
||||
result, response = srv.select(imap_quote(imap_mailbox), roflag)
|
||||
if result != 'OK':
|
||||
unexpected_error("selecting '%s' failed; server says: '%s'." \
|
||||
% (mailbox, response[0]))
|
||||
|
@ -1548,6 +1669,7 @@ def imap_find_mailboxes(srv, mailbox):
|
|||
vprint("Looking for mailboxes matching '%s'..." % curbox)
|
||||
else:
|
||||
vprint("Looking for mailbox '%s'..." % curbox)
|
||||
curbox = mod_utf7_encode(curbox.decode(userencoding))
|
||||
result, response = srv.list(pattern=imap_quote(curbox))
|
||||
if result != 'OK':
|
||||
unexpected_error("LIST command failed; " \
|
||||
|
@ -1577,6 +1699,13 @@ def imap_find_mailboxes(srv, mailbox):
|
|||
else:
|
||||
attrs, name = m.groups()
|
||||
name = imap_unquote(name)
|
||||
try:
|
||||
name = mod_utf7_decode(name)
|
||||
except ValueError:
|
||||
vprint("Mailbox name '%s' returned by server doesn't look like "
|
||||
"modified UTF-7" % name)
|
||||
name = name.decode('utf-8')
|
||||
name = name.encode(userencoding)
|
||||
if '\\noselect' in attrs.lower().split():
|
||||
vprint("skipping not selectable mailbox '%s'" % name)
|
||||
continue
|
||||
|
@ -1599,16 +1728,24 @@ def imap_guess_mailboxnames(srv, mailbox):
|
|||
hdelim = imap_getdelim(srv)
|
||||
vprint("IMAP namespace prefix: '%s', hierarchy delimiter: '%s'" % \
|
||||
(nsprefix, hdelim))
|
||||
if mailbox.startswith(nsprefix):
|
||||
if mailbox.upper() == "INBOX" or \
|
||||
(hdelim is not None and mailbox.upper().startswith("INBOX" + hdelim)):
|
||||
# INBOX is not a real mailbox name, so namespace prefixes do not apply
|
||||
# to INBOX and its children
|
||||
boxnames = [mailbox]
|
||||
elif mailbox.startswith(nsprefix):
|
||||
boxnames = [mailbox]
|
||||
else:
|
||||
boxnames = [nsprefix + mailbox]
|
||||
if os.path.sep in mailbox and hdelim is not None:
|
||||
mailbox = mailbox.replace(os.path.sep, hdelim)
|
||||
if mailbox.startswith(nsprefix):
|
||||
if mailbox.upper().startswith("INBOX" + hdelim):
|
||||
boxnames.append(mailbox)
|
||||
if nsprefix:
|
||||
boxnames.append(nsprefix + mailbox)
|
||||
else:
|
||||
if mailbox.startswith(nsprefix):
|
||||
boxnames.append(mailbox)
|
||||
if nsprefix:
|
||||
boxnames.append(nsprefix + mailbox)
|
||||
return boxnames
|
||||
|
||||
|
||||
|
|
486
archivemail.1
486
archivemail.1
|
@ -1,486 +0,0 @@
|
|||
.\" This manpage has been automatically generated by docbook2man
|
||||
.\" from a DocBook document. This tool can be found at:
|
||||
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
|
||||
.\" Please send any bug reports, improvements, comments, patches,
|
||||
.\" etc. to Steve Cheng <steve@ggi-project.org>.
|
||||
.TH "ARCHIVEMAIL" "1" "09 August 2010" "SP" ""
|
||||
|
||||
.SH NAME
|
||||
archivemail \- archive and compress your old email
|
||||
.SH SYNOPSIS
|
||||
|
||||
\fBarchivemail\fR [ \fBoptions\fR ] \fB\fIMAILBOX\fB\fR\fI ...\fR
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
archivemail is a tool for archiving and compressing old email in mailboxes.
|
||||
By default it will read the mailbox \fIMAILBOX\fR, moving messages
|
||||
that are older that the specified number of days (180 by default) to a
|
||||
\fBmbox\fR(5)-format mailbox in the same directory that is compressed
|
||||
with \fBgzip\fR(1)\&.
|
||||
It can also just delete old email rather than archive it.
|
||||
.PP
|
||||
By default, \fBarchivemail\fR derives the archive filename from the
|
||||
mailbox name by appending an \fI_archive\fR suffix to the mailbox
|
||||
name. For example, if you run \fBarchivemail\fR on a mailbox called
|
||||
\fIexsouthrock\fR, the archive will be created with the
|
||||
filename \fIexsouthrock_archive.gz\fR\&.
|
||||
This default behavior can be overridden with command line options, choosing
|
||||
a custom suffix, a prefix, or a completely custom name for the archive.
|
||||
.PP
|
||||
\fBarchivemail\fR supports reading \fBIMAP\fR,
|
||||
\fBMaildir\fR, \fBMH\fR and \fBmbox\fR-format
|
||||
mailboxes, but always writes \fBmbox\fR-format archives.
|
||||
.PP
|
||||
Messages that are flagged important are not archived or deleted unless
|
||||
explicitely requested with the \fB--include-flagged\fR option.
|
||||
Also, \fBarchivemail\fR can be configured not to archive unread mail, or
|
||||
to only archive messages larger than a specified size.
|
||||
.PP
|
||||
To archive an \fBIMAP\fR-format mailbox, use the format
|
||||
\fIimap://username:password@server/mailbox\fR to specify the mailbox.
|
||||
\fBarchivemail\fR will expand wildcards in \fBIMAP\fR mailbox
|
||||
names according to RFC 3501, which says: ``The character "*" is a wildcard, and matches zero or more characters at this
|
||||
position. The character "%" is similar to "*", but it does not match a
|
||||
hierarchy delimiter.''
|
||||
You can omit the password from the URL; use the
|
||||
\fB--pwfile\fR option to make \fBarchivemail\fR read the
|
||||
password from a file, or alternatively just enter it upon request.
|
||||
If the \fB--pwfile\fR option is set, \fBarchivemail\fR does not
|
||||
look for a password in the URL, and the colon is not considered a
|
||||
delimiter.
|
||||
Substitute '\fBimap\fR\&' with '\fBimaps\fR\&', and
|
||||
\fBarchivemail\fR will establish a secure SSL connection.
|
||||
See below for more \fBIMAP\fR peculiarities.
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
\fB -d \fINUM\fB, --days=\fINUM\fB\fR
|
||||
Archive messages older than \fINUM\fR days.
|
||||
The default is 180. This option is incompatible with the
|
||||
\fB--date\fR option below.
|
||||
.TP
|
||||
\fB -D \fIDATE\fB, --date=\fIDATE\fB\fR
|
||||
Archive messages older than \fIDATE\fR\&.
|
||||
\fIDATE\fR can be a date string in ISO format (eg '2002-04-23'),
|
||||
Internet format (eg '23 Apr 2002') or Internet format with full month names
|
||||
(eg '23 April 2002'). Two-digit years are not supported.
|
||||
This option is incompatible with the \fB--days\fR option above.
|
||||
.TP
|
||||
\fB -o \fIPATH\fB, --output-dir=\fIPATH\fB\fR
|
||||
Use the directory name \fIPATH\fR to store the
|
||||
mailbox archives. The default is the same directory as the mailbox to be
|
||||
read.
|
||||
.TP
|
||||
\fB -P \fIFILE\fB, --pwfile=\fIFILE\fB\fR
|
||||
Read IMAP password from file \fIFILE\fR
|
||||
instead of from the command line. Note that this will probably not work if you
|
||||
are archiving folders from more than one IMAP account.
|
||||
.TP
|
||||
\fB -F \fISTRING\fB, --filter-append=\fISTRING\fB\fR
|
||||
Append \fISTRING\fR to the IMAP filter string.
|
||||
For IMAP wizards.
|
||||
.TP
|
||||
\fB -p \fINAME\fB, --prefix=\fINAME\fB\fR
|
||||
Prefix \fINAME\fR to the archive name.
|
||||
\fINAME\fR is expanded by the \fBpython\fR(1) function
|
||||
\fBtime.strftime()\fR, which means that you can specify special
|
||||
directives in \fINAME\fR to make an archive named after the archive
|
||||
cut-off date.
|
||||
See the discussion of the \fB--suffix\fR option for a list of valid
|
||||
\fBstrftime()\fR directives.
|
||||
The default is not to add a prefix.
|
||||
.TP
|
||||
\fB -s \fINAME\fB, --suffix=\fINAME\fB\fR
|
||||
Use the suffix \fINAME\fR to create the filename used for archives.
|
||||
The default is \fI_archive\fR, unless a prefix is specified.
|
||||
|
||||
Like a prefix, the suffix \fINAME\fR is expanded by the \fBpython\fR(1)
|
||||
function \fBtime.strftime()\fR with the archive cut-off date.
|
||||
\fBtime.strftime()\fR understands the following directives:
|
||||
.RS
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%a\fR
|
||||
Locale's abbreviated weekday name.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%A\fR
|
||||
Locale's full weekday name.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%b\fR
|
||||
Locale's abbreviated month name.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%B\fR
|
||||
Locale's full month name.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%c\fR
|
||||
Locale's appropriate date and time representation.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%d\fR
|
||||
Day of the month as a decimal number [01,31].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%H\fR
|
||||
Hour (24-hour clock) as a decimal number [00,23].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%I\fR
|
||||
Hour (12-hour clock) as a decimal number [01,12].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%j\fR
|
||||
Day of the year as a decimal number [001,366].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%m\fR
|
||||
Month as a decimal number [01,12].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%M\fR
|
||||
Minute as a decimal number [00,59].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%p\fR
|
||||
Locale's equivalent of either AM or PM.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%S\fR
|
||||
Second as a decimal number [00,61]. (1)
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%U\fR
|
||||
Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%w\fR
|
||||
Weekday as a decimal number [0(Sunday),6].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%W\fR
|
||||
Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%x\fR
|
||||
Locale's appropriate date representation.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%X\fR
|
||||
Locale's appropriate time representation.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%y\fR
|
||||
Year without century as a decimal number [00,99].
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%Y\fR
|
||||
Year with century as a decimal number.
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%Z\fR
|
||||
Time zone name (or by no characters if no time zone exists).
|
||||
.TP 0.2i
|
||||
\(bu
|
||||
\fB%%\fR
|
||||
A literal "%" character.
|
||||
.RE
|
||||
.TP
|
||||
\fB -a \fINAME\fB, --archive-name=\fINAME\fB\fR
|
||||
Use \fINAME\fR as the archive name, ignoring the name
|
||||
of the mailbox that is archived.
|
||||
Like prefixes and suffixes, \fINAME\fR is expanded by
|
||||
\fBstrftime()\fR with the archive cut-off date.
|
||||
Because it hard-codes the archive name, this option cannot be used when
|
||||
archiving multiple mailboxes.
|
||||
.TP
|
||||
\fB -S \fINUM\fB, --size=\fINUM\fB\fR
|
||||
Only archive messages that are \fINUM\fR bytes or
|
||||
greater.
|
||||
.TP
|
||||
\fB -n, --dry-run\fR
|
||||
Don't write to any files -- just show what would have been done. This is
|
||||
useful for testing to see how many messages would have been archived.
|
||||
.TP
|
||||
\fB -u, --preserve-unread\fR
|
||||
Do not archive any messages that have not yet been read. \fBarchivemail\fR
|
||||
determines if a message in a \fBmbox\fR-format or
|
||||
\fBMH\fR-format mailbox has been read by looking at the
|
||||
\fBStatus\fR header (if it exists). If the status
|
||||
header is equal to 'RO' or 'OR' then \fBarchivemail\fR assumes the
|
||||
message has been read. \fBarchivemail\fR determines if a
|
||||
\fBmaildir\fR message has
|
||||
been read by looking at the filename. If the filename contains an 'S' after
|
||||
\fI:2,\fR then it assumes the message has been read.
|
||||
.TP
|
||||
\fB --dont-mangle\fR
|
||||
Do not mangle lines in message bodies beginning with "From ". When archiving
|
||||
a message from a mailbox not in \fBmbox\fR format, by default
|
||||
\fBarchivemail\fR mangles such lines by prepending a '>' to them, since mail
|
||||
user agents might otherwise interpret these lines as message separators.
|
||||
Messages from \fBmbox\fR folders are never mangled. See \fBmbox\fR(5) for more
|
||||
information.
|
||||
.TP
|
||||
\fB --delete\fR
|
||||
Delete rather than archive old mail. Use this option with caution!
|
||||
.TP
|
||||
\fB --copy\fR
|
||||
Copy rather than archive old mail.
|
||||
Creates an archive, but the archived messages are not deleted from the
|
||||
originating mailbox, which is left unchanged.
|
||||
This is a complement to the \fB--delete\fR option, and mainly useful for
|
||||
testing purposes.
|
||||
Note that multiple passes will create duplicates, since messages are blindly
|
||||
appended to an existing archive.
|
||||
.TP
|
||||
\fB --all\fR
|
||||
Archive all messages, without distinction.
|
||||
.TP
|
||||
\fB --include-flagged\fR
|
||||
Normally messages that are flagged important are not archived or deleted. If
|
||||
you specify this option, these messages can be archived or deleted just like
|
||||
any other message.
|
||||
.TP
|
||||
\fB --no-compress\fR
|
||||
Do not compress any archives.
|
||||
.TP
|
||||
\fB --warn-duplicate\fR
|
||||
Warn about duplicate \fBMessage-ID\fRs that appear in the input
|
||||
mailbox.
|
||||
.TP
|
||||
\fB -v, --verbose\fR
|
||||
Reports lots of extra debugging information about what is going on.
|
||||
.TP
|
||||
\fB --debug-imap=\fINUM\fB\fR
|
||||
Set IMAP debugging level. This makes \fBarchivemail\fR dump its
|
||||
conversation with the IMAP server and some internal IMAP
|
||||
processing to stdout\&. Higher values for \fINUM\fR give more
|
||||
elaborate output. Set \fINUM\fR to 4 to see all exchanged
|
||||
IMAP commands. (Actually, \fINUM\fR is just passed
|
||||
literally to imaplib.Debug\&.)
|
||||
.TP
|
||||
\fB -q, --quiet\fR
|
||||
Turns on quiet mode. Do not print any statistics about how many messages were
|
||||
archived. This should be used if you are running \fBarchivemail\fR from
|
||||
cron.
|
||||
.TP
|
||||
\fB -V, --version\fR
|
||||
Display the version of \fBarchivemail\fR and exit.
|
||||
.TP
|
||||
\fB -h, --help\fR
|
||||
Display brief summary information about how to run \fBarchivemail\fR\&.
|
||||
.SH "NOTES"
|
||||
.PP
|
||||
\fBarchivemail\fR requires \fBpython\fR(1) version 2.3 or later.
|
||||
When reading an \fBmbox\fR-format mailbox, \fBarchivemail\fR will
|
||||
create a lockfile with the extension \fI\&.lock\fR so that
|
||||
procmail will not deliver to the mailbox while it is being processed. It will
|
||||
also create an advisory lock on the mailbox using \fBlockf\fR(2)\&.
|
||||
The archive is locked in the same way when it is updated.
|
||||
\fBarchivemail\fR will also complain and abort if a 3rd-party modifies the
|
||||
mailbox while it is being read.
|
||||
.PP
|
||||
\fBarchivemail\fR will always attempt to preserve the
|
||||
last-access and last-modify times of the input mailbox. Archive
|
||||
mailboxes are always created with a mode of \fB0600\fR\&.
|
||||
If \fBarchivemail\fR finds a pre-existing archive mailbox it
|
||||
will append rather than overwrite that archive.
|
||||
\fBarchivemail\fR will refuse to operate on mailboxes that are symbolic
|
||||
links.
|
||||
.PP
|
||||
\fBarchivemail\fR attempts to find the delivery date of a message by
|
||||
looking for valid dates in the following headers, in order of precedence:
|
||||
\fBDelivery-date\fR,
|
||||
\fBReceived\fR,
|
||||
\fBResent-Date\fR and
|
||||
\fBDate\fR\&.
|
||||
If it cannot find any valid date in these headers, it
|
||||
will use the last-modified file timestamp on \fBMH\fR and
|
||||
\fBMaildir\fR format mailboxes, or the date on the
|
||||
\fBFrom\fR line on \fBmbox\fR-format mailboxes.
|
||||
.PP
|
||||
When archiving mailboxes with leading dots in the name,
|
||||
\fBarchivemail\fR will strip the dots off the archive name, so
|
||||
that the resulting archive file is not hidden.
|
||||
This is not done if the \fB--prefix\fR or
|
||||
\fB--archive-name\fR option is used.
|
||||
Should there really be mailboxes distinguished only by leading dots in the
|
||||
name, they will thus be archived to the same archive file by default.
|
||||
.PP
|
||||
A conversion from other formats to \fBmbox\fR(5) will silently overwrite existing
|
||||
\fBStatus\fR and \fBX-Status\fR message headers.
|
||||
.SS "IMAP"
|
||||
.PP
|
||||
When \fBarchivemail\fR processes an \fBIMAP\fR folder, all messages
|
||||
in that folder will have their \\Recent flag unset, and they will
|
||||
probably not show up as 'new' in your user agent later on.
|
||||
There is no way around this, it's just how \fBIMAP\fR works.
|
||||
This does not apply, however, if you run \fBarchivemail\fR with the options
|
||||
\fB--dry-run\fR or \fB--copy\fR\&.
|
||||
.PP
|
||||
\fBarchivemail\fR relies on server-side searches to determine the messages
|
||||
that should be archived.
|
||||
When matching message dates, \fBIMAP\fR servers refer to server internal
|
||||
message dates, and these may differ from both delivery time of a message and
|
||||
its \fBDate\fR header.
|
||||
Also, there exist broken servers which do not implement server side searches.
|
||||
.SS "IMAP URLS"
|
||||
.PP
|
||||
\fBarchivemail\fR\&'s \fBIMAP\fR URL parser was written
|
||||
with the RFC 2882 (\fIInternet Message
|
||||
Format\fR) rules for the local-part of email addresses
|
||||
in mind.
|
||||
So, rather than enforcing an URL-style encoding of non-ascii
|
||||
and reserved characters, it allows to double-quote the username and password.
|
||||
If your username or password contains the delimiter characters '@' or ':', just
|
||||
quote it like this:
|
||||
\fIimap://"username@bogus.com":"password"@imap.bogus.com/mailbox\fR\&.
|
||||
You can use a backslash to escape double-quotes that are part of a quoted
|
||||
username or password.
|
||||
Note that quoting only a substring will not work, and be aware that your shell
|
||||
will probably remove unprotected quotes or backslashes.
|
||||
.PP
|
||||
\fBarchivemail\fR tries to be smart when handling mailbox paths.
|
||||
In particular, it will automatically add an IMAP NAMESPACE
|
||||
prefix to the mailbox path if necessary; and if you are archiving a subfolder,
|
||||
you can use the slash as a path separator instead of the IMAP server's
|
||||
internal representation.
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
.PP
|
||||
To archive all messages in the mailbox \fIdebian-user\fR that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
\fIdebian-user_archive.gz\fR in the current directory:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail debian-user\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To archive all messages in the mailbox \fIdebian-user\fR that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
\fIdebian-user_October_2001.gz\fR (where the current month and
|
||||
year is April, 2002) in the current directory:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --suffix '_%B_%Y' debian-user\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To archive all messages in the mailbox \fIcm-melb\fR that
|
||||
are older than the first of January 2002 to a compressed mailbox called
|
||||
\fIcm-melb_archive.gz\fR in the current directory:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --date'1 Jan 2002' cm-melb\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
Exactly the same as the above example, using an ISO date format instead:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --date=2002-01-01 cm-melb\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To delete all messages in the mailbox \fIspam\fR that
|
||||
are older than 30 days:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --delete --days=30 spam\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To archive all read messages in the mailbox \fIincoming\fR that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
\fIincoming_archive.gz\fR in the current directory:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --preserve-unread incoming\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To archive all messages in the mailbox \fIreceived\fR that
|
||||
are older than 180 days to an uncompressed mailbox called
|
||||
\fIreceived_archive\fR in the current directory:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --no-compress received\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To archive all mailboxes in the directory \fI$HOME/Mail\fR
|
||||
that are older than 90 days to compressed mailboxes in the
|
||||
\fI$HOME/Mail/Archive\fR directory:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail -d90 -o $HOME/Mail/Archive $HOME/Mail/*\fR
|
||||
.fi
|
||||
.PP
|
||||
.PP
|
||||
To archive all mails older than 180 days from the given \fBIMAP\fR
|
||||
INBOX to a compressed mailbox INBOX_archive.gz in the
|
||||
\fI$HOME/Mail/Archive\fR directory, quoting the password and
|
||||
reading it from the environment variable \fBPASSWORD\fR:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail -o $HOME/Mail/Archive imaps://user:'"'$PASSWORD'"'@example.org/INBOX\fR
|
||||
.fi
|
||||
.PP
|
||||
Note the protected quotes.
|
||||
.PP
|
||||
.PP
|
||||
To archive all mails older than 180 days in subfolders of "foo" on the
|
||||
given \fBIMAP\fR server to corresponding archives in the current
|
||||
working directory, reading the password from the file
|
||||
\fI~/imap-pass.txt\fR:
|
||||
|
||||
.nf
|
||||
bash$ \fBarchivemail --pwfile=~/imap-pass.txt imaps://user@example.org/foo/*\fR
|
||||
.fi
|
||||
.SH "TIPS"
|
||||
.PP
|
||||
Probably the best way to run \fBarchivemail\fR is from your \fBcrontab\fR(5)
|
||||
file, using the \fB--quiet\fR option.
|
||||
Don't forget to try the \fB--dry-run\fR and perhaps the
|
||||
\fB--copy\fR option for non-destructive testing.
|
||||
.SH "EXIT STATUS"
|
||||
.PP
|
||||
Normally the exit status is 0. Nonzero indicates an unexpected error.
|
||||
.SH "BUGS"
|
||||
.PP
|
||||
If an \fBIMAP\fR mailbox path contains slashes, the archive filename
|
||||
will be derived from the basename of the mailbox.
|
||||
If the server's folder separator differs from the Unix slash and is used in the
|
||||
\fBIMAP\fR URL, however, the whole path will be considered
|
||||
the basename of the mailbox.
|
||||
E.g. the two URLs
|
||||
\fBimap://user@example.com/folder/subfolder\fR and
|
||||
\fBimap://user@example.com/folder.subfolder\fR will be
|
||||
archived in \fIsubfolder_archive.gz\fR and
|
||||
\fIfolder.subfolder_archive.gz\fR, respectively, although they
|
||||
might refer to the same \fBIMAP\fR mailbox.
|
||||
.PP
|
||||
\fBarchivemail\fR does not support reading \fBMMDF\fR or
|
||||
\fBBabyl\fR-format mailboxes. In fact, it will probably think it is
|
||||
reading an \fBmbox\fR-format mailbox and cause all sorts of problems.
|
||||
.PP
|
||||
\fBarchivemail\fR is still too slow, but if you are running from \fBcrontab\fR(5)
|
||||
you won't care. Archiving \fBmaildir\fR-format mailboxes should be
|
||||
a lot quicker than \fBmbox\fR-format mailboxes since it is less
|
||||
painful for the original mailbox to be reconstructed after selective message
|
||||
removal.
|
||||
.SH "SEE ALSO"
|
||||
|
||||
\fBpython\fR(1), \fBgzip\fR(1), \fBmutt\fR(1), \fBprocmail\fR(1)
|
||||
.SH "URL"
|
||||
.PP
|
||||
The \fBarchivemail\fR home page is currently hosted at
|
||||
sourceforge <URL:http://archivemail.sourceforge.net>
|
||||
.SH "AUTHOR"
|
||||
.PP
|
||||
This manual page was written by Paul Rodger <paul at paulrodger dot
|
||||
com>\&. Updated and supplemented by Nikolaus Schulz
|
||||
<microschulz@web.de>
|
715
archivemail.sgml
715
archivemail.sgml
|
@ -1,715 +0,0 @@
|
|||
<!DOCTYPE RefEntry PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
|
||||
|
||||
<!ENTITY lockf "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/lockf/</RefEntryTitle>
|
||||
<ManVolNum/2/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY gzip "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/gzip/</RefEntryTitle>
|
||||
<ManVolNum/1/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY mutt "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/mutt/</RefEntryTitle>
|
||||
<ManVolNum/1/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY procmail "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/procmail/</RefEntryTitle>
|
||||
<ManVolNum/1/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY python "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/python/</RefEntryTitle>
|
||||
<ManVolNum/1/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY seteuid "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/seteuid/</RefEntryTitle>
|
||||
<ManVolNum/2/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY crontab "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/crontab/</RefEntryTitle>
|
||||
<ManVolNum/5/</CiteRefEntry>">
|
||||
|
||||
<!ENTITY mbox "<CiteRefEntry>
|
||||
<RefEntryTitle><Command/mbox/</RefEntryTitle>
|
||||
<ManVolNum/5/</CiteRefEntry>">
|
||||
]>
|
||||
|
||||
<RefEntry>
|
||||
|
||||
<DocInfo><Date>9 August 2010</Date></DocInfo>
|
||||
|
||||
<RefMeta>
|
||||
<RefEntryTitle>archivemail</RefEntryTitle>
|
||||
<ManVolNum>1</ManVolNum>
|
||||
<RefMiscInfo>SP</RefMiscInfo>
|
||||
</RefMeta>
|
||||
|
||||
<RefNameDiv>
|
||||
<RefName>archivemail</RefName>
|
||||
<RefPurpose>archive and compress your old email</RefPurpose>
|
||||
</RefNameDiv>
|
||||
|
||||
<RefSynopsisDiv>
|
||||
<CmdSynopsis>
|
||||
|
||||
<Command/archivemail/
|
||||
<Arg><Option>options</Option></Arg>
|
||||
<Arg choice=req rep=repeat><Replaceable/MAILBOX/</Arg>
|
||||
|
||||
</CmdSynopsis>
|
||||
</RefSynopsisDiv>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Description</Title>
|
||||
|
||||
<Para>
|
||||
archivemail is a tool for archiving and compressing old email in mailboxes.
|
||||
By default it will read the mailbox <Replaceable/MAILBOX/, moving messages
|
||||
that are older that the specified number of days (180 by default) to a
|
||||
&mbox;-format mailbox in the same directory that is compressed
|
||||
with &gzip;.
|
||||
It can also just delete old email rather than archive it.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
By default, <command/archivemail/ derives the archive filename from the
|
||||
mailbox name by appending an <filename/_archive/ suffix to the mailbox
|
||||
name. For example, if you run <Command/archivemail/ on a mailbox called
|
||||
<filename>exsouthrock</filename>, the archive will be created with the
|
||||
filename <filename>exsouthrock_archive.gz</filename>.
|
||||
This default behavior can be overridden with command line options, choosing
|
||||
a custom suffix, a prefix, or a completely custom name for the archive.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
<Command/archivemail/ supports reading <application/IMAP/,
|
||||
<application/Maildir/, <application/MH/ and <application/mbox/-format
|
||||
mailboxes, but always writes <application/mbox/-format archives.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
Messages that are flagged important are not archived or deleted unless
|
||||
explicitely requested with the <Option>--include-flagged</Option> option.
|
||||
Also, <command/archivemail/ can be configured not to archive unread mail, or
|
||||
to only archive messages larger than a specified size.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
To archive an <application/IMAP/-format mailbox, use the format
|
||||
<replaceable>imap://username:password@server/mailbox
|
||||
</replaceable> to specify the mailbox.
|
||||
<application/archivemail/ will expand wildcards in <application/IMAP/ mailbox
|
||||
names according to <acronym>RFC</acronym> 3501, which says: <quote>
|
||||
The character "*" is a wildcard, and matches zero or more characters at this
|
||||
position. The character "%" is similar to "*", but it does not match a
|
||||
hierarchy delimiter.</quote>
|
||||
You can omit the password from the <acronym/URL/; use the
|
||||
<option>--pwfile</option> option to make <command/archivemail/ read the
|
||||
password from a file, or alternatively just enter it upon request.
|
||||
If the <option>--pwfile</option> option is set, <command/archivemail/ does not
|
||||
look for a password in the <acronym/URL/, and the colon is not considered a
|
||||
delimiter.
|
||||
Substitute '<userinput/imap/' with '<userinput/imaps/', and
|
||||
<command/archivemail/ will establish a secure <acronym/SSL/ connection.
|
||||
See below for more <application/IMAP/ peculiarities.
|
||||
</Para>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Options</Title>
|
||||
|
||||
<VariableList>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-d <Replaceable/NUM/, --days=<Replaceable/NUM/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Archive messages older than <Replaceable/NUM/ days.
|
||||
The default is 180. This option is incompatible with the
|
||||
<Option/--date/ option below.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-D <Replaceable/DATE/, --date=<Replaceable/DATE/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Archive messages older than <Replaceable/DATE/.
|
||||
<Replaceable/DATE/ can be a date string in ISO format (eg '2002-04-23'),
|
||||
Internet format (eg '23 Apr 2002') or Internet format with full month names
|
||||
(eg '23 April 2002'). Two-digit years are not supported.
|
||||
This option is incompatible with the <Option/--days/ option above.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-o <Replaceable/PATH/, --output-dir=<Replaceable/PATH/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Use the directory name <Replaceable/PATH/ to store the
|
||||
mailbox archives. The default is the same directory as the mailbox to be
|
||||
read.
|
||||
</Para></ListItem>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-P <Replaceable/FILE/, --pwfile=<Replaceable/FILE/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Read <acronym/IMAP/ password from file <Replaceable/FILE/
|
||||
instead of from the command line. Note that this will probably not work if you
|
||||
are archiving folders from more than one IMAP account.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-F <Replaceable/STRING/,
|
||||
--filter-append=<Replaceable/STRING/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Append <Replaceable/STRING/ to the <acronym/IMAP/ filter string.
|
||||
For <acronym/IMAP/ wizards.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-p <Replaceable/NAME/, --prefix=<Replaceable/NAME/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Prefix <Replaceable/NAME/ to the archive name.
|
||||
<Replaceable/NAME/ is expanded by the &python; function
|
||||
<application/time.strftime()/, which means that you can specify special
|
||||
directives in <Replaceable/NAME/ to make an archive named after the archive
|
||||
cut-off date.
|
||||
See the discussion of the <Option>--suffix</Option> option for a list of valid
|
||||
<application/strftime()/ directives.
|
||||
The default is not to add a prefix.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-s <Replaceable/NAME/, --suffix=<Replaceable/NAME/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Use the suffix <Replaceable/NAME/ to create the filename used for archives.
|
||||
The default is <filename>_archive</filename>, unless a prefix is specified.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
Like a prefix, the suffix <Replaceable/NAME/ is expanded by the &python;
|
||||
function <application/time.strftime()/ with the archive cut-off date.
|
||||
<application/time.strftime()/ understands the following directives:
|
||||
|
||||
<itemizedlist mark='none'>
|
||||
<listitem><para><option>%a</option>
|
||||
Locale's abbreviated weekday name.</para></listitem>
|
||||
<listitem><para><option>%A</option>
|
||||
Locale's full weekday name.</para></listitem>
|
||||
<listitem><para><option>%b</option>
|
||||
Locale's abbreviated month name.</para></listitem>
|
||||
<listitem><para><option>%B</option>
|
||||
Locale's full month name.</para></listitem>
|
||||
<listitem><para><option>%c</option>
|
||||
Locale's appropriate date and time representation.</para></listitem>
|
||||
<listitem><para><option>%d</option>
|
||||
Day of the month as a decimal number [01,31].</para></listitem>
|
||||
<listitem><para><option>%H</option>
|
||||
Hour (24-hour clock) as a decimal number [00,23].</para></listitem>
|
||||
<listitem><para><option>%I</option>
|
||||
Hour (12-hour clock) as a decimal number [01,12].</para></listitem>
|
||||
<listitem><para><option>%j</option>
|
||||
Day of the year as a decimal number [001,366].</para></listitem>
|
||||
<listitem><para><option>%m</option>
|
||||
Month as a decimal number [01,12].</para></listitem>
|
||||
<listitem><para><option>%M</option>
|
||||
Minute as a decimal number [00,59].</para></listitem>
|
||||
<listitem><para><option>%p</option>
|
||||
Locale's equivalent of either AM or PM.</para></listitem>
|
||||
<listitem><para><option>%S</option>
|
||||
Second as a decimal number [00,61]. (1)</para></listitem>
|
||||
<listitem><para><option>%U</option>
|
||||
Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.</para></listitem>
|
||||
<listitem><para><option>%w</option>
|
||||
Weekday as a decimal number [0(Sunday),6].</para></listitem>
|
||||
<listitem><para><option>%W</option>
|
||||
Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.</para></listitem>
|
||||
<listitem><para><option>%x</option>
|
||||
Locale's appropriate date representation.</para></listitem>
|
||||
<listitem><para><option>%X</option>
|
||||
Locale's appropriate time representation.</para></listitem>
|
||||
<listitem><para><option>%y</option>
|
||||
Year without century as a decimal number [00,99].</para></listitem>
|
||||
<listitem><para><option>%Y</option>
|
||||
Year with century as a decimal number.</para></listitem>
|
||||
<listitem><para><option>%Z</option>
|
||||
Time zone name (or by no characters if no time zone exists).</para></listitem>
|
||||
<listitem><para><option>%%</option>
|
||||
A literal "%" character.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-a <Replaceable/NAME/, --archive-name=<Replaceable/NAME/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Use <Replaceable/NAME/ as the archive name, ignoring the name
|
||||
of the mailbox that is archived.
|
||||
Like prefixes and suffixes, <Replaceable/NAME/ is expanded by
|
||||
<application/strftime()/ with the archive cut-off date.
|
||||
Because it hard-codes the archive name, this option cannot be used when
|
||||
archiving multiple mailboxes.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-S <Replaceable/NUM/, --size=<Replaceable/NUM/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>Only archive messages that are <Replaceable/NUM/ bytes or
|
||||
greater.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-n, --dry-run</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Don't write to any files -- just show what would have been done. This is
|
||||
useful for testing to see how many messages would have been archived.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-u, --preserve-unread</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Do not archive any messages that have not yet been read. <command/archivemail/
|
||||
determines if a message in a <application/mbox/-format or
|
||||
<application/MH/-format mailbox has been read by looking at the
|
||||
<application/Status/ header (if it exists). If the status
|
||||
header is equal to 'RO' or 'OR' then <application/archivemail/ assumes the
|
||||
message has been read. <command/archivemail/ determines if a
|
||||
<application/maildir/ message has
|
||||
been read by looking at the filename. If the filename contains an 'S' after
|
||||
<filename>:2,</filename> then it assumes the message has been read.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--dont-mangle</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Do not mangle lines in message bodies beginning with "From ". When archiving
|
||||
a message from a mailbox not in <application/mbox/ format, by default
|
||||
<command/archivemail/ mangles such lines by prepending a '>' to them, since mail
|
||||
user agents might otherwise interpret these lines as message separators.
|
||||
Messages from <application/mbox/ folders are never mangled. See &mbox; for more
|
||||
information.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--delete</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Delete rather than archive old mail. Use this option with caution!
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--copy</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Copy rather than archive old mail.
|
||||
Creates an archive, but the archived messages are not deleted from the
|
||||
originating mailbox, which is left unchanged.
|
||||
This is a complement to the <option/--delete/ option, and mainly useful for
|
||||
testing purposes.
|
||||
Note that multiple passes will create duplicates, since messages are blindly
|
||||
appended to an existing archive.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--all</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Archive all messages, without distinction.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--include-flagged</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Normally messages that are flagged important are not archived or deleted. If
|
||||
you specify this option, these messages can be archived or deleted just like
|
||||
any other message.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--no-compress</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Do not compress any archives.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--warn-duplicate</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Warn about duplicate <application/Message-ID/s that appear in the input
|
||||
mailbox.</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-v, --verbose</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Reports lots of extra debugging information about what is going on.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>--debug-imap=<Replaceable/NUM/</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Set <acronym/IMAP/ debugging level. This makes <Command/archivemail/ dump its
|
||||
conversation with the <acronym/IMAP/ server and some internal <acronym/IMAP/
|
||||
processing to <Literal/stdout/. Higher values for <Replaceable/NUM/ give more
|
||||
elaborate output. Set <Replaceable/NUM/ to 4 to see all exchanged
|
||||
<acronym/IMAP/ commands. (Actually, <Replaceable/NUM/ is just passed
|
||||
literally to <Literal/imaplib.Debug/.)
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-q, --quiet</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Turns on quiet mode. Do not print any statistics about how many messages were
|
||||
archived. This should be used if you are running <Command/archivemail/ from
|
||||
cron.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-V, --version</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Display the version of <Command/archivemail/ and exit.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
|
||||
<VarListEntry>
|
||||
<Term>
|
||||
<Option>-h, --help</Option>
|
||||
</Term>
|
||||
<ListItem><Para>
|
||||
Display brief summary information about how to run <Command/archivemail/.
|
||||
</Para></ListItem>
|
||||
</VarListEntry>
|
||||
</VariableList>
|
||||
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Notes</Title>
|
||||
<Para>
|
||||
<Command/archivemail/ requires &python; version 2.3 or later.
|
||||
When reading an <application/mbox/-format mailbox, <command/archivemail/ will
|
||||
create a lockfile with the extension <filename>.lock</filename> so that
|
||||
procmail will not deliver to the mailbox while it is being processed. It will
|
||||
also create an advisory lock on the mailbox using &lockf;.
|
||||
The archive is locked in the same way when it is updated.
|
||||
<command/archivemail/ will also complain and abort if a 3rd-party modifies the
|
||||
mailbox while it is being read.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
<Command/archivemail/ will always attempt to preserve the
|
||||
last-access and last-modify times of the input mailbox. Archive
|
||||
mailboxes are always created with a mode of <application/0600/.
|
||||
If <Command/archivemail/ finds a pre-existing archive mailbox it
|
||||
will append rather than overwrite that archive.
|
||||
<Command/archivemail/ will refuse to operate on mailboxes that are symbolic
|
||||
links.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
<Command/archivemail/ attempts to find the delivery date of a message by
|
||||
looking for valid dates in the following headers, in order of precedence:
|
||||
<application/Delivery-date/,
|
||||
<application/Received/,
|
||||
<application/Resent-Date/ and
|
||||
<application/Date/.
|
||||
If it cannot find any valid date in these headers, it
|
||||
will use the last-modified file timestamp on <application/MH/ and
|
||||
<application/Maildir/ format mailboxes, or the date on the
|
||||
<application/From/ line on <application/mbox/-format mailboxes.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
When archiving mailboxes with leading dots in the name,
|
||||
<application/archivemail/ will strip the dots off the archive name, so
|
||||
that the resulting archive file is not hidden.
|
||||
This is not done if the <Option>--prefix</Option> or
|
||||
<Option>--archive-name</Option> option is used.
|
||||
Should there really be mailboxes distinguished only by leading dots in the
|
||||
name, they will thus be archived to the same archive file by default.
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
A conversion from other formats to &mbox; will silently overwrite existing
|
||||
<application/Status/ and <application/X-Status/ message headers.
|
||||
</Para>
|
||||
|
||||
<RefSect2>
|
||||
<Title><acronym/IMAP/</Title>
|
||||
<Para>
|
||||
When <command/archivemail/ processes an <application/IMAP/ folder, all messages
|
||||
in that folder will have their <literal/\Recent/ flag unset, and they will
|
||||
probably not show up as 'new' in your user agent later on.
|
||||
There is no way around this, it's just how <application/IMAP/ works.
|
||||
This does not apply, however, if you run <command/archivemail/ with the options
|
||||
<option/--dry-run/ or <option/--copy/.
|
||||
</Para>
|
||||
<Para>
|
||||
<command/archivemail/ relies on server-side searches to determine the messages
|
||||
that should be archived.
|
||||
When matching message dates, <application/IMAP/ servers refer to server internal
|
||||
message dates, and these may differ from both delivery time of a message and
|
||||
its <application/Date/ header.
|
||||
Also, there exist broken servers which do not implement server side searches.
|
||||
</Para>
|
||||
<RefSect3><Title><acronym/IMAP/ <acronym/URLs/</Title>
|
||||
<Para>
|
||||
<command/archivemail/'s <application/IMAP/ <acronym/URL/ parser was written
|
||||
with the <acronym>RFC</acronym> 2882 (<citetitle>Internet Message
|
||||
Format</citetitle>) rules for the <token>local-part</token> of email addresses
|
||||
in mind.
|
||||
So, rather than enforcing an <acronym/URL/-style encoding of non-<acronym/ascii/
|
||||
and reserved characters, it allows to double-quote the username and password.
|
||||
If your username or password contains the delimiter characters '@' or ':', just
|
||||
quote it like this:
|
||||
<replaceable>imap://"username@bogus.com":"password"@imap.bogus.com/mailbox
|
||||
</replaceable>.
|
||||
You can use a backslash to escape double-quotes that are part of a quoted
|
||||
username or password.
|
||||
Note that quoting only a substring will not work, and be aware that your shell
|
||||
will probably remove unprotected quotes or backslashes.
|
||||
</Para>
|
||||
<Para>
|
||||
<command/archivemail/ tries to be smart when handling mailbox paths.
|
||||
In particular, it will automatically add an <acronym/IMAP/ <literal/NAMESPACE/
|
||||
prefix to the mailbox path if necessary; and if you are archiving a subfolder,
|
||||
you can use the slash as a path separator instead of the <acronym/IMAP/ server's
|
||||
internal representation.
|
||||
</Para>
|
||||
</RefSect3>
|
||||
</RefSect2>
|
||||
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Examples</Title>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all messages in the mailbox <filename>debian-user</filename> that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
<filename>debian-user_archive.gz</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail debian-user</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all messages in the mailbox <filename>debian-user</filename> that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
<filename>debian-user_October_2001.gz</filename> (where the current month and
|
||||
year is April, 2002) in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --suffix '_%B_%Y' debian-user</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all messages in the mailbox <filename>cm-melb</filename> that
|
||||
are older than the first of January 2002 to a compressed mailbox called
|
||||
<filename>cm-melb_archive.gz</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --date'1 Jan 2002' cm-melb</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
Exactly the same as the above example, using an ISO date format instead:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --date=2002-01-01 cm-melb</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To delete all messages in the mailbox <filename>spam</filename> that
|
||||
are older than 30 days:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --delete --days=30 spam</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all read messages in the mailbox <filename>incoming</filename> that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
<filename>incoming_archive.gz</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --preserve-unread incoming</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all messages in the mailbox <filename>received</filename> that
|
||||
are older than 180 days to an uncompressed mailbox called
|
||||
<filename>received_archive</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --no-compress received</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all mailboxes in the directory <filename>$HOME/Mail</filename>
|
||||
that are older than 90 days to compressed mailboxes in the
|
||||
<filename>$HOME/Mail/Archive</filename> directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail -d90 -o $HOME/Mail/Archive $HOME/Mail/*</userinput>
|
||||
</screen>
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all mails older than 180 days from the given <application/IMAP/
|
||||
INBOX to a compressed mailbox INBOX_archive.gz in the
|
||||
<filename>$HOME/Mail/Archive</filename> directory, quoting the password and
|
||||
reading it from the environment variable <envar>PASSWORD</envar>:
|
||||
</Para>
|
||||
<!-- I'm open to suggestions how to avoid making such a super-long line here. -->
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail -o $HOME/Mail/Archive imaps://user:'"'$PASSWORD'"'@example.org/INBOX</userinput>
|
||||
</screen>
|
||||
<Para>
|
||||
Note the protected quotes.
|
||||
</Para>
|
||||
</InformalExample>
|
||||
|
||||
<InformalExample>
|
||||
<Para>
|
||||
To archive all mails older than 180 days in subfolders of "foo" on the
|
||||
given <application/IMAP/ server to corresponding archives in the current
|
||||
working directory, reading the password from the file
|
||||
<filename>~/imap-pass.txt</filename>:
|
||||
</Para>
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --pwfile=~/imap-pass.txt imaps://user@example.org/foo/*</userinput>
|
||||
</screen>
|
||||
</InformalExample>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Tips</Title>
|
||||
<Para>
|
||||
Probably the best way to run <Command/archivemail/ is from your &crontab;
|
||||
file, using the <Option>--quiet</Option> option.
|
||||
Don't forget to try the <Option>--dry-run</Option> and perhaps the
|
||||
<Option>--copy</Option> option for non-destructive testing.
|
||||
</Para>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Exit Status</Title>
|
||||
<SimPara>Normally the exit status is 0. Nonzero indicates an unexpected error.
|
||||
</SimPara>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Bugs</Title>
|
||||
<SimPara>
|
||||
If an <application/IMAP/ mailbox path contains slashes, the archive filename
|
||||
will be derived from the basename of the mailbox.
|
||||
If the server's folder separator differs from the Unix slash and is used in the
|
||||
<application/IMAP/ <acronym/URL/, however, the whole path will be considered
|
||||
the basename of the mailbox.
|
||||
E.g. the two <acronym/URL/s
|
||||
<userinput>imap://user@example.com/folder/subfolder</userinput> and
|
||||
<userinput>imap://user@example.com/folder.subfolder</userinput> will be
|
||||
archived in <filename>subfolder_archive.gz</filename> and
|
||||
<filename>folder.subfolder_archive.gz</filename>, respectively, although they
|
||||
might refer to the same <application/IMAP/ mailbox.
|
||||
</SimPara>
|
||||
<SimPara>
|
||||
<command/archivemail/ does not support reading <application/MMDF/ or
|
||||
<application/Babyl/-format mailboxes. In fact, it will probably think it is
|
||||
reading an <application/mbox/-format mailbox and cause all sorts of problems.
|
||||
</SimPara>
|
||||
|
||||
<SimPara>
|
||||
<Command/archivemail/ is still too slow, but if you are running from &crontab;
|
||||
you won't care. Archiving <application/maildir/-format mailboxes should be
|
||||
a lot quicker than <application/mbox/-format mailboxes since it is less
|
||||
painful for the original mailbox to be reconstructed after selective message
|
||||
removal.
|
||||
</SimPara>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>See Also</Title>
|
||||
<SimpleList>
|
||||
<Member> &python;, &gzip;, &mutt;, &procmail;</Member>
|
||||
</SimpleList>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Url</Title>
|
||||
<SimPara>The <Command/archivemail/ home page is currently hosted at
|
||||
<ulink type="http" url="http://archivemail.sourceforge.net">sourceforge</ulink>
|
||||
</SimPara>
|
||||
</RefSect1>
|
||||
|
||||
<RefSect1>
|
||||
<Title>Author</Title>
|
||||
<SimPara> This manual page was written by Paul Rodger <paul at paulrodger dot
|
||||
com>. Updated and supplemented by Nikolaus Schulz
|
||||
<email>microschulz@web.de</email></SimPara>
|
||||
</RefSect1>
|
||||
|
||||
</RefEntry>
|
|
@ -0,0 +1,794 @@
|
|||
<?xml version='1.0'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"file:///usr/share/xml/docbook/schema/dtd/4.2/docbookx.dtd" [
|
||||
|
||||
<!ENTITY lockf '<citerefentry>
|
||||
<refentrytitle><emphasis role="bold">lockf</emphasis></refentrytitle>
|
||||
<manvolnum>2</manvolnum></citerefentry>'>
|
||||
|
||||
<!ENTITY gzip '<citerefentry>
|
||||
<refentrytitle><emphasis role="bold">gzip</emphasis></refentrytitle>
|
||||
<manvolnum>1</manvolnum></citerefentry>'>
|
||||
|
||||
<!ENTITY procmail '<citerefentry>
|
||||
<refentrytitle><emphasis role="bold">procmail</emphasis></refentrytitle>
|
||||
<manvolnum>1</manvolnum></citerefentry>'>
|
||||
|
||||
<!ENTITY python '<citerefentry>
|
||||
<refentrytitle><emphasis role="bold">python</emphasis></refentrytitle>
|
||||
<manvolnum>1</manvolnum></citerefentry>'>
|
||||
|
||||
<!ENTITY crontab '<citerefentry>
|
||||
<refentrytitle><emphasis role="bold">crontab</emphasis></refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry>'>
|
||||
|
||||
<!ENTITY mbox '<citerefentry>
|
||||
<refentrytitle><emphasis role="bold"><acronym>mbox</acronym></emphasis></refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry>'>
|
||||
]>
|
||||
|
||||
<refentry>
|
||||
|
||||
<docinfo><date>5 July 2011</date></docinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>archivemail</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="manual">archivemail user manual</refmiscinfo>
|
||||
<refmiscinfo class="source">archivemail 0.9.0</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>archivemail</refname>
|
||||
<refpurpose>archive and compress your old email</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
|
||||
<command>archivemail</command>
|
||||
<arg><option>options</option></arg>
|
||||
<arg choice="req" rep="repeat"><replaceable>MAILBOX</replaceable></arg>
|
||||
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
<command>archivemail</command> is a tool for archiving and compressing old
|
||||
email in mailboxes.
|
||||
By default it will read the mailbox <replaceable>MAILBOX</replaceable>, moving
|
||||
messages that are older than the specified number of days (180 by default) to
|
||||
a &mbox;-format mailbox in the same directory that is compressed with &gzip;.
|
||||
It can also just delete old email rather than archive it.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default, <command>archivemail</command> derives the archive filename from
|
||||
the mailbox name by appending an <filename>_archive</filename> suffix to the
|
||||
mailbox name. For example, if you run <command>archivemail</command> on a
|
||||
mailbox called <filename>exsouthrock</filename>, the archive will be created
|
||||
with the filename <filename>exsouthrock_archive.gz</filename>.
|
||||
This default behavior can be overridden with command line options, choosing
|
||||
a custom suffix, a prefix, or a completely custom name for the archive.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>archivemail</command> supports reading <acronym>IMAP</acronym>,
|
||||
<acronym>Maildir</acronym>, <acronym>MH</acronym> and
|
||||
<acronym>mbox</acronym>-format mailboxes, but always writes
|
||||
<acronym>mbox</acronym>-format archives.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Messages that are flagged important are not archived or deleted unless
|
||||
explicitly requested with the <option>--include-flagged</option> option.
|
||||
Also, <command>archivemail</command> can be configured not to archive unread
|
||||
mail, or to only archive messages larger than a specified size.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To archive an <acronym>IMAP</acronym>-format mailbox, use the format
|
||||
<replaceable>imap://username:password@server/mailbox </replaceable> to specify
|
||||
the mailbox.
|
||||
<command>archivemail</command> will expand wildcards in
|
||||
<acronym>IMAP</acronym> mailbox names according to
|
||||
<citation><acronym>RFC</acronym> 3501</citation>, which says: <quote>The
|
||||
character "*" is a wildcard, and matches zero or more characters at this
|
||||
position. The character "%" is similar to "*", but it does not match a
|
||||
hierarchy delimiter.</quote>
|
||||
You can omit the password from the <acronym>URL</acronym>; use the
|
||||
<option>--pwfile</option> option to make <command>archivemail</command> read
|
||||
the password from a file, or alternatively just enter it upon request.
|
||||
If the <option>--pwfile</option> option is set, <command>archivemail</command>
|
||||
does not look for a password in the <acronym>URL</acronym>, and the colon is
|
||||
not considered a delimiter.
|
||||
Substitute <replaceable>imap</replaceable> with
|
||||
<replaceable>imaps</replaceable>, and <command>archivemail</command> will
|
||||
establish a secure <acronym>SSL</acronym> connection.
|
||||
See below for more <acronym>IMAP</acronym> peculiarities.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-d <replaceable>NUM</replaceable></option></term>
|
||||
<term><option>--days=<replaceable>NUM</replaceable></option></term>
|
||||
<listitem><para>Archive messages older than <replaceable>NUM</replaceable>
|
||||
days. The default is 180. This option is incompatible with the
|
||||
<option>--date</option> option below.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-D <replaceable>DATE</replaceable></option></term>
|
||||
<term><option>--date=<replaceable>DATE</replaceable></option></term>
|
||||
<listitem><para>Archive messages older than <replaceable>DATE</replaceable>.
|
||||
<replaceable>DATE</replaceable> can be a date string in ISO format (eg
|
||||
<quote>2002-04-23</quote>), Internet format (<abbrev>eg</abbrev> <quote>23 Apr
|
||||
2002</quote>) or Internet format with full month names (<abbrev>eg</abbrev>
|
||||
<quote>23 April 2002</quote>). Two-digit years are not supported.
|
||||
This option is incompatible with the <option>--days</option> option above.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-o <replaceable>PATH</replaceable></option></term>
|
||||
<term><option>--output-dir=<replaceable>PATH</replaceable></option></term>
|
||||
<listitem><para>Use the directory name <replaceable>PATH</replaceable> to
|
||||
store the mailbox archives. The default is the same directory as the mailbox
|
||||
to be read.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-P <replaceable>FILE</replaceable></option></term>
|
||||
<term><option>--pwfile=<replaceable>FILE</replaceable></option></term>
|
||||
<listitem><para>Read <acronym>IMAP</acronym> password from file
|
||||
<replaceable>FILE</replaceable> instead of from the command line. Note
|
||||
that this will probably not work if you are archiving folders from
|
||||
more than one IMAP account.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-F <replaceable>STRING</replaceable></option></term>
|
||||
<term><option>--filter-append=<replaceable>STRING</replaceable></option></term>
|
||||
<listitem><para>Append <replaceable>STRING</replaceable> to the
|
||||
<acronym>IMAP</acronym> filter string.
|
||||
For <acronym>IMAP</acronym> wizards.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-p <replaceable>NAME</replaceable></option></term>
|
||||
<term><option>--prefix=<replaceable>NAME</replaceable></option></term>
|
||||
<listitem><para>Prefix <replaceable>NAME</replaceable> to the archive name.
|
||||
<replaceable>NAME</replaceable> is expanded by the &python; function
|
||||
<function>time.strftime()</function>, which means that you can specify special
|
||||
directives in <replaceable>NAME</replaceable> to make an archive named after
|
||||
the archive cut-off date.
|
||||
See the discussion of the <option>--suffix</option> option for a list of valid
|
||||
<function>strftime()</function> directives.
|
||||
The default is not to add a prefix.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-s <replaceable>NAME</replaceable></option></term>
|
||||
<term><option>--suffix=<replaceable>NAME</replaceable></option></term>
|
||||
<listitem><para>
|
||||
Use the suffix <replaceable>NAME</replaceable> to create the filename used for
|
||||
archives. The default is <filename>_archive</filename>, unless a prefix is
|
||||
specified.
|
||||
</para>
|
||||
<para>
|
||||
Like a prefix, the suffix <replaceable>NAME</replaceable> is expanded by the
|
||||
&python; function <function>time.strftime()</function> with the archive
|
||||
cut-off date. <function>time.strftime()</function> understands the following
|
||||
directives:
|
||||
<variablelist id="strftime">
|
||||
<varlistentry><term><code>%a</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's abbreviated weekday name.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%A</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's full weekday name.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%b</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's abbreviated month name.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%B</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's full month name.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%c</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's appropriate date and time representation.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%d</code></term>
|
||||
<listitem><simpara>
|
||||
Day of the month as a decimal number [01,31].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%H</code></term>
|
||||
<listitem><simpara>
|
||||
Hour (24-hour clock) as a decimal number [00,23].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%I</code></term>
|
||||
<listitem><simpara>
|
||||
Hour (12-hour clock) as a decimal number [01,12].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%j</code></term>
|
||||
<listitem><simpara>
|
||||
Day of the year as a decimal number [001,366].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%m</code></term>
|
||||
<listitem><simpara>
|
||||
Month as a decimal number [01,12].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%M</code></term>
|
||||
<listitem><simpara>
|
||||
Minute as a decimal number [00,59].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%p</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's equivalent of either AM or PM.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%S</code></term>
|
||||
<listitem><simpara>
|
||||
Second as a decimal number [00,61]. (1)
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%U</code></term>
|
||||
<listitem><simpara>
|
||||
Week number of the year (Sunday as the first day of the week)
|
||||
as a decimal number [00,53]. All days in a new year preceding
|
||||
the first Sunday are considered to be in week 0.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%w</code></term>
|
||||
<listitem><simpara>
|
||||
Weekday as a decimal number [0(Sunday),6].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%W</code></term>
|
||||
<listitem><simpara>
|
||||
Week number of the year (Monday as the first day of the week)
|
||||
as a decimal number [00,53]. All days in a new year preceding
|
||||
the first Sunday are considered to be in week 0.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%x</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's appropriate date representation.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%X</code></term>
|
||||
<listitem><simpara>
|
||||
Locale's appropriate time representation.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%y</code></term>
|
||||
<listitem><simpara>
|
||||
Year without century as a decimal number [00,99].
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%Y</code></term>
|
||||
<listitem><simpara>
|
||||
Year with century as a decimal number.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%Z</code></term>
|
||||
<listitem><simpara>
|
||||
Time zone name (or by no characters if no time zone exists).
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry><term><code>%%</code></term>
|
||||
<listitem><simpara>
|
||||
A literal <quote>%</quote> character.
|
||||
</simpara></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-a <replaceable>NAME</replaceable></option></term>
|
||||
<term><option>--archive-name=<replaceable>NAME</replaceable></option></term>
|
||||
<listitem><para>Use <replaceable>NAME</replaceable> as the archive name,
|
||||
ignoring the name of the mailbox that is archived.
|
||||
Like prefixes and suffixes, <replaceable>NAME</replaceable> is expanded by
|
||||
<function>time.strftime()</function> with the archive cut-off date.
|
||||
Because it hard-codes the archive name, this option cannot be used when
|
||||
archiving multiple mailboxes.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-S <replaceable>NUM</replaceable></option></term>
|
||||
<term><option>--size=<replaceable>NUM</replaceable></option></term>
|
||||
<listitem><para>Only archive messages that are <replaceable>NUM</replaceable>
|
||||
bytes or greater.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-n</option></term>
|
||||
<term><option>--dry-run</option></term>
|
||||
<listitem><para>
|
||||
Don't write to any files -- just show what would have been done. This is
|
||||
useful for testing to see how many messages would have been archived.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-u</option></term>
|
||||
<term><option>--preserve-unread</option></term>
|
||||
<listitem><para>
|
||||
Do not archive any messages that have not yet been read.
|
||||
<command>archivemail</command> determines if a message in a
|
||||
<acronym>mbox</acronym>-format or <acronym>MH</acronym>-format mailbox has
|
||||
been read by looking at the <literal>Status</literal> header (if it exists).
|
||||
If the status header is equal to <quote><literal>RO</literal></quote> or
|
||||
<quote><literal>OR</literal></quote> then <command>archivemail</command>
|
||||
assumes the message has been read.
|
||||
<command>archivemail</command> determines if a <acronym>maildir</acronym>
|
||||
message has been read by looking at the filename.
|
||||
If the filename contains an <quote><literal>S</literal></quote> after
|
||||
<filename>:2,</filename> then it assumes the message has been read.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--dont-mangle</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Do not mangle lines in message bodies beginning with
|
||||
<quote><literal>From </literal></quote>.
|
||||
When archiving a message from a mailbox not in <acronym>mbox</acronym>
|
||||
format, by default <command>archivemail</command> mangles such lines by
|
||||
prepending a <quote><literal>></literal></quote> to them, since mail user
|
||||
agents might otherwise interpret these lines as message separators.
|
||||
Messages from <acronym>mbox</acronym> folders are never mangled. See &mbox;
|
||||
for more information.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--delete</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Delete rather than archive old mail. Use this option with caution!
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--copy</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Copy rather than archive old mail.
|
||||
Creates an archive, but the archived messages are not deleted from the
|
||||
originating mailbox, which is left unchanged.
|
||||
This is a complement to the <option>--delete</option> option, and mainly
|
||||
useful for testing purposes.
|
||||
Note that multiple passes will create duplicates, since messages are blindly
|
||||
appended to an existing archive.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--all</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Archive all messages, without distinction.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--include-flagged</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Normally messages that are flagged important are not archived or deleted. If
|
||||
you specify this option, these messages can be archived or deleted just like
|
||||
any other message.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--no-compress</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Do not compress any archives.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--warn-duplicate</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Warn about duplicate <literal>Message-ID</literal>s that appear in the input
|
||||
mailbox.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--verbose</option></term>
|
||||
<listitem><para>
|
||||
Reports lots of extra debugging information about what is going on.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--debug-imap=<replaceable>NUM</replaceable></option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Set <acronym>IMAP</acronym> debugging level. This makes
|
||||
<command>archivemail</command> dump its conversation with the
|
||||
<acronym>IMAP</acronym> server and some internal <acronym>IMAP</acronym>
|
||||
processing to <literal>stdout</literal>. Higher values for
|
||||
<replaceable>NUM</replaceable> give more elaborate output. Set
|
||||
<replaceable>NUM</replaceable> to 4 to see all exchanged
|
||||
<acronym>IMAP</acronym> commands. (Actually, <replaceable>NUM</replaceable>
|
||||
is just passed literally to <literal>imaplib.Debug</literal>.)
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-q</option></term>
|
||||
<term><option>--quiet</option></term>
|
||||
<listitem><para>
|
||||
Turns on quiet mode. Do not print any statistics about how many messages were
|
||||
archived. This should be used if you are running
|
||||
<command>archivemail</command> from cron.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-V</option></term>
|
||||
<term><option>--version</option></term>
|
||||
<listitem><para>
|
||||
Display the version of <command>archivemail</command> and exit.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-h</option></term>
|
||||
<term><option>--help</option></term>
|
||||
<listitem><para>
|
||||
Display brief summary information about how to run
|
||||
<command>archivemail</command>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para>
|
||||
<command>archivemail</command> requires &python; version 2.3 or later.
|
||||
When reading an <acronym>mbox</acronym>-format mailbox,
|
||||
<command>archivemail</command> will create a lockfile with the extension
|
||||
<filename class="extension">.lock</filename> so that &procmail; will not
|
||||
deliver to the mailbox while it is being processed. It will also create an
|
||||
advisory lock on the mailbox using &lockf;. The archive is locked in the same
|
||||
way when it is updated.
|
||||
<command>archivemail</command> will also complain and abort if a 3rd-party
|
||||
modifies the mailbox while it is being read.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>archivemail</command> will always attempt to preserve the last-access
|
||||
and last-modify times of the input mailbox. Archive mailboxes are always
|
||||
created with a mode of <literal>0600</literal>.
|
||||
If <command>archivemail</command> finds a pre-existing archive mailbox it will
|
||||
append rather than overwrite that archive.
|
||||
<command>archivemail</command> will refuse to operate on mailboxes that are
|
||||
symbolic links.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>archivemail</command> attempts to find the delivery date of a message
|
||||
by looking for valid dates in the following headers, in order of precedence:
|
||||
<literal>Delivery-date</literal>,
|
||||
<literal>Received</literal>,
|
||||
<literal>Resent-Date</literal> and
|
||||
<literal>Date</literal>.
|
||||
If it cannot find any valid date in these headers, it will use the
|
||||
last-modified file timestamp on <acronym>MH</acronym> and
|
||||
<acronym>Maildir</acronym> format mailboxes, or the date on the
|
||||
<literal>From_</literal> line on <acronym>mbox</acronym>-format mailboxes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When archiving mailboxes with leading dots in the name,
|
||||
<command>archivemail</command> will strip the dots off the archive name, so
|
||||
that the resulting archive file is not hidden.
|
||||
This is not done if the <option>--prefix</option> or
|
||||
<option>--archive-name</option> option is used.
|
||||
Should there really be mailboxes distinguished only by leading dots in the
|
||||
name, they will thus be archived to the same archive file by default.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A conversion from other formats to &mbox; will silently overwrite existing
|
||||
<literal>Status</literal> and <literal>X-Status</literal> message headers.
|
||||
</para>
|
||||
|
||||
<refsect2>
|
||||
<title><acronym>IMAP</acronym></title>
|
||||
<para>
|
||||
When <command>archivemail</command> processes an <acronym>IMAP</acronym>
|
||||
folder, all messages in that folder will have their <literal>\Recent</literal>
|
||||
flag unset, and they will probably not show up as <quote>new</quote> in your
|
||||
user agent later on.
|
||||
There is no way around this, it's just how <acronym>IMAP</acronym> works.
|
||||
This does not apply, however, if you run <command>archivemail</command> with
|
||||
the options <option>--dry-run</option> or <option>--copy</option>.
|
||||
</para>
|
||||
<para>
|
||||
<command>archivemail</command> relies on server-side searches to determine the
|
||||
messages that should be archived.
|
||||
When matching message dates, <acronym>IMAP</acronym> servers refer to server
|
||||
internal message dates, and these may differ from both delivery time of a
|
||||
message and its <literal>Date</literal> header.
|
||||
Also, there exist broken servers which do not implement server side searches.
|
||||
</para>
|
||||
<refsect3><title><acronym>IMAP</acronym> <acronym>URL</acronym>s</title>
|
||||
<para>
|
||||
<command>archivemail</command>'s <acronym>IMAP</acronym>
|
||||
<acronym>URL</acronym> parser was written with the <acronym>RFC</acronym> 2882
|
||||
(<citetitle>Internet Message Format</citetitle>) rules for the
|
||||
<token>local-part</token> of email addresses in mind.
|
||||
So, rather than enforcing an <acronym>URL</acronym>-style encoding of
|
||||
non-<acronym>ascii</acronym> and reserved characters, it allows you to
|
||||
double-quote the username and password.
|
||||
If your username or password contains the delimiter characters
|
||||
<quote>@</quote> or <quote>:</quote>, just quote it like this:
|
||||
<replaceable>imap://"username@bogus.com":"password"@imap.bogus.com/mailbox</replaceable>.
|
||||
You can use a backslash to escape double-quotes that are part of a quoted
|
||||
username or password.
|
||||
Note that quoting only a substring will not work, and be aware that your shell
|
||||
will probably remove unprotected quotes or backslashes.
|
||||
</para>
|
||||
<para>
|
||||
Similarly, there is no need to percent-encode non-<acronym>ascii</acronym>
|
||||
characters in <acronym>IMAP</acronym> mailbox names.
|
||||
As long as your locale is configured properly, <command>archivemail</command>
|
||||
should handle these without problems.
|
||||
Note, however, that due to limitations of the <acronym>IMAP</acronym>
|
||||
protocol, non-<acronym>ascii</acronym> characters do not mix well with
|
||||
wildcards in mailbox names.
|
||||
</para>
|
||||
<para>
|
||||
<command>archivemail</command> tries to be smart when handling mailbox paths.
|
||||
In particular, it will automatically add an <acronym>IMAP</acronym>
|
||||
<literal>NAMESPACE</literal> prefix to the mailbox path if necessary; and if
|
||||
you are archiving a subfolder, you can use the slash as a path separator
|
||||
instead of the <acronym>IMAP</acronym> server's internal representation.
|
||||
</para>
|
||||
</refsect3>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all messages in the mailbox <filename>debian-user</filename> that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
<filename>debian-user_archive.gz</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail debian-user</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all messages in the mailbox <filename>debian-user</filename> that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
<filename>debian-user_October_2001.gz</filename> (where the current month and
|
||||
year is April, 2002) in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --suffix '_%B_%Y' debian-user</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all messages in the mailbox <filename>cm-melb</filename> that
|
||||
are older than the first of January 2002 to a compressed mailbox called
|
||||
<filename>cm-melb_archive.gz</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --date='1 Jan 2002' cm-melb</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
Exactly the same as the above example, using an <acronym>ISO</acronym> date
|
||||
format instead:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --date=2002-01-01 cm-melb</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To delete all messages in the mailbox <filename>spam</filename> that
|
||||
are older than 30 days:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --delete --days=30 spam</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all read messages in the mailbox <filename>incoming</filename> that
|
||||
are older than 180 days to a compressed mailbox called
|
||||
<filename>incoming_archive.gz</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --preserve-unread incoming</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all messages in the mailbox <filename>received</filename> that
|
||||
are older than 180 days to an uncompressed mailbox called
|
||||
<filename>received_archive</filename> in the current directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --no-compress received</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all mailboxes in the directory <filename>$HOME/Mail</filename>
|
||||
that are older than 90 days to compressed mailboxes in the
|
||||
<filename>$HOME/Mail/Archive</filename> directory:
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail -d90 -o $HOME/Mail/Archive $HOME/Mail/*</userinput>
|
||||
</screen>
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all mails older than 180 days from the given
|
||||
<acronym>IMAP</acronym> <literal>INBOX</literal> to a compressed mailbox
|
||||
<filename>INBOX_archive.gz</filename> in the
|
||||
<filename>$HOME/Mail/Archive</filename> directory, quoting the password and
|
||||
reading it from the environment variable <envar>PASSWORD</envar>:
|
||||
</para>
|
||||
<!-- i'm open to suggestions how to avoid making such a super-long line here. -->
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail -o $HOME/Mail/Archive imaps://user:'"'$PASSWORD'"'@example.org/INBOX</userinput>
|
||||
</screen>
|
||||
<para>
|
||||
Note the protected quotes.
|
||||
</para>
|
||||
</informalexample>
|
||||
|
||||
<informalexample>
|
||||
<para>
|
||||
To archive all mails older than 180 days in subfolders of <filename
|
||||
class="directory">foo</filename> on the given <acronym>IMAP</acronym>
|
||||
server to corresponding archives in the current working directory, reading the
|
||||
password from the file <filename>~/imap-pass.txt</filename>:
|
||||
</para>
|
||||
<screen>
|
||||
<prompt>bash$ </prompt><userinput>archivemail --pwfile=~/imap-pass.txt imaps://user@example.org/foo/*</userinput>
|
||||
</screen>
|
||||
</informalexample>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Tips</title>
|
||||
<para>
|
||||
Probably the best way to run <command>archivemail</command> is from your
|
||||
&crontab; file, using the <option>--quiet</option> option.
|
||||
Don't forget to try the <option>--dry-run</option> and perhaps the
|
||||
<option>--copy</option> option for non-destructive testing.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Exit Status</title>
|
||||
<simpara>Normally the exit status is 0. Nonzero indicates an unexpected error.
|
||||
</simpara>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Bugs</title>
|
||||
<simpara>
|
||||
If an <acronym>IMAP</acronym> mailbox path contains slashes, the archive
|
||||
filename will be derived from the basename of the mailbox.
|
||||
If the server's folder separator differs from the Unix slash and is used in
|
||||
the <acronym>IMAP</acronym> <acronym>URL</acronym>, however, the whole path
|
||||
will be considered the basename of the mailbox.
|
||||
<abbrev>E.g.</abbrev> the two <acronym>URL</acronym>s
|
||||
<userinput>imap://user@example.com/folder/subfolder</userinput> and
|
||||
<userinput>imap://user@example.com/folder.subfolder</userinput> will be
|
||||
archived in <filename>subfolder_archive.gz</filename> and
|
||||
<filename>folder.subfolder_archive.gz</filename>, respectively, although they
|
||||
might refer to the same <acronym>IMAP</acronym> mailbox.
|
||||
</simpara>
|
||||
<simpara>
|
||||
<command>archivemail</command> does not support reading
|
||||
<acronym>MMDF</acronym> or <acronym>Babyl</acronym>-format mailboxes. In fact,
|
||||
it will probably think it is reading an <acronym>mbox</acronym>-format mailbox
|
||||
and cause all sorts of problems.
|
||||
</simpara>
|
||||
|
||||
<simpara>
|
||||
<command>archivemail</command> is still too slow, but if you are running from
|
||||
&crontab; you won't care. Archiving <acronym>maildir</acronym>-format
|
||||
mailboxes should be a lot quicker than <acronym>mbox</acronym>-format
|
||||
mailboxes since it is less painful for the original mailbox to be
|
||||
reconstructed after selective message removal.
|
||||
</simpara>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>&mbox;</member>
|
||||
<member>&crontab;</member>
|
||||
<member>&python;</member>
|
||||
<member>&procmail;</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title><acronym>Url</acronym></title>
|
||||
<simpara>The <command>archivemail</command> home page is currently hosted at
|
||||
<ulink type="http" url="http://archivemail.sourceforge.net">sourceforge</ulink>
|
||||
</simpara>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<simpara> This manual page was written by Paul Rodger <paul at paulrodger
|
||||
dot com>. Updated and supplemented by Nikolaus Schulz
|
||||
<email>microschulz@web.de</email></simpara>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
40
db2html.dsl
40
db2html.dsl
|
@ -1,40 +0,0 @@
|
|||
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
|
||||
|
||||
<!ENTITY dbstyle SYSTEM "/usr/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl" CDATA DSSSL>
|
||||
]>
|
||||
|
||||
<style-sheet>
|
||||
<style-specification use="docbook">
|
||||
<style-specification-body>
|
||||
|
||||
(define %css-decoration%
|
||||
; Enable html element decoration with 'style=...' css?
|
||||
#t)
|
||||
|
||||
(define %stylesheet%
|
||||
; Needed if we want to use a css file
|
||||
"manpage.css")
|
||||
|
||||
(define %shade-verbatim%
|
||||
;; Should verbatim environments be shaded?
|
||||
#t)
|
||||
|
||||
; Override $refentry-body$ from dbrfntry.dsl
|
||||
; to add a hr after the refentry title h1.
|
||||
(define ($refentry-body$)
|
||||
(let ((id (element-id (current-node))))
|
||||
(make sequence
|
||||
(make element gi: "H1"
|
||||
(make sequence
|
||||
(make element gi: "A"
|
||||
attributes: (list (list "NAME" id))
|
||||
(empty-sosofo))
|
||||
(element-title-sosofo (current-node))))
|
||||
; Now add hr element after h1.
|
||||
(make empty-element gi: "HR")
|
||||
(process-children))))
|
||||
|
||||
</style-specification-body>
|
||||
</style-specification>
|
||||
<external-specification id="docbook" document="dbstyle">
|
||||
</style-sheet>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
<xsl:import href="/usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl"/>
|
||||
<xsl:param name="html.stylesheet">manpage.css</xsl:param>
|
||||
<xsl:template name="user.header.content">
|
||||
<h1>archivemail</h1>
|
||||
<hr/>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
<xsl:import href="/usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl"/>
|
||||
|
||||
<!-- Use .TP list for the variablelist describing the strtime() directives. -->
|
||||
<!-- This hack aligns the indented paragraphs horizontally with their -->
|
||||
<!-- labels. -->
|
||||
<xsl:template match="variablelist[attribute::id='strftime']/varlistentry">
|
||||
<xsl:text>.TP </xsl:text>
|
||||
<xsl:for-each select="term">
|
||||
<xsl:variable name="content">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:variable>
|
||||
<xsl:value-of select="normalize-space($content)"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="position() = last()"/> <!-- do nothing -->
|
||||
<xsl:otherwise>
|
||||
<!-- * if we have multiple terms in the same varlistentry, generate -->
|
||||
<!-- * a separator (", " by default) -->
|
||||
<xsl:value-of select="$variablelist.term.separator"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:for-each>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
<hr>
|
||||
<div id="status">
|
||||
<strong>Latest version: 0.8.1</strong><br>
|
||||
Released on 2010-09-30
|
||||
<strong>Latest version: 0.9.0</strong><br>
|
||||
Released on 2011-07-09
|
||||
</div>
|
||||
<h2>What is it?</h2>
|
||||
<p>
|
||||
|
|
|
@ -3,9 +3,13 @@ h2 {
|
|||
font-variant: small-caps;
|
||||
font-size: 170%;
|
||||
}
|
||||
.INFORMALEXAMPLE {
|
||||
.informalexample {
|
||||
margin-bottom: 1.2em;
|
||||
}
|
||||
div.INFORMALEXAMPLE .SCREEN {
|
||||
div.informalexample .screen {
|
||||
margin-left: 2ex;
|
||||
}
|
||||
|
||||
a#strftime + dl dt { float: left; margin: 0.3ex 0; width: 1.5em; }
|
||||
a#strftime + dl dd { float: left; margin: 0.3ex 0; margin-left: 1.2em; width: 90%; }
|
||||
dt { clear: left; }
|
||||
|
|
4
setup.py
4
setup.py
|
@ -20,7 +20,7 @@ check_python_version()
|
|||
from distutils.core import setup
|
||||
|
||||
setup(name="archivemail",
|
||||
version="0.8.1",
|
||||
version="0.9.0",
|
||||
description="archive and compress old email",
|
||||
license="GNU GPL",
|
||||
url="http://archivemail.sourceforge.net/",
|
||||
|
@ -29,5 +29,5 @@ setup(name="archivemail",
|
|||
maintainer="Nikolaus Schulz, Peter Poeml",
|
||||
maintainer_email="nikosch@users.sourceforge.net, poeml@users.sourceforge.net",
|
||||
scripts=["archivemail"],
|
||||
data_files=[("man/man1", ["archivemail.1"])],
|
||||
data_files=[("share/man/man1", ["archivemail.1"])],
|
||||
)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
body {
|
||||
font-family: "Times New Roman", serif;
|
||||
font-size: 12pt;
|
||||
padding: 2%;
|
||||
line-height: 130%;
|
||||
margin: 0;
|
||||
|
@ -26,9 +24,6 @@ h2 {
|
|||
padding: 0;
|
||||
font-size: 150%;
|
||||
}
|
||||
pre, tt, kbd, code, pre samp {
|
||||
font-family: "Courier 10 Pitch", Courier, "Courier New", monospace;
|
||||
}
|
||||
img {border: none;}
|
||||
a {
|
||||
text-decoration: underline;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#! /usr/bin/env python
|
||||
############################################################################
|
||||
# Copyright (C) 2002 Paul Rodger <paul@paulrodger.com>
|
||||
# (C) 2006-2010 Nikolaus Schulz <microschulz@web.de>
|
||||
# (C) 2006-2011 Nikolaus Schulz <microschulz@web.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -30,12 +30,12 @@ TODO: add tests for:
|
|||
import sys
|
||||
|
||||
def check_python_version():
|
||||
"""Abort if we are running on python < v2.3"""
|
||||
too_old_error = "This test script requires python version 2.3 or later. " + \
|
||||
"""Abort if we are running on python < v2.4"""
|
||||
too_old_error = "This test script requires python version 2.4 or later. " + \
|
||||
"Your version of python is:\n%s" % sys.version
|
||||
try:
|
||||
version = sys.version_info # we might not even have this function! :)
|
||||
if (version[0] < 2) or (version[0] == 2 and version[1] < 3):
|
||||
if (version[0] < 2) or (version[0] == 2 and version[1] < 4):
|
||||
print too_old_error
|
||||
sys.exit(1)
|
||||
except AttributeError:
|
||||
|
@ -85,14 +85,16 @@ class FixedGzipFile(gzip.GzipFile):
|
|||
"""GzipFile with seek method accepting whence parameter."""
|
||||
def seek(self, offset, whence=0):
|
||||
try:
|
||||
gzip.GzipFile.seek(self, offset, whence)
|
||||
# Try calling gzip.GzipFile.seek with the whence parameter.
|
||||
# For Python >= 2.7, it returns the new offset; pass that on.
|
||||
return gzip.GzipFile.seek(self, offset, whence)
|
||||
except TypeError:
|
||||
if whence:
|
||||
if whence == 1:
|
||||
offset = self.offset + offset
|
||||
else:
|
||||
raise ValueError('Seek from end not supported')
|
||||
gzip.GzipFile.seek(self, offset)
|
||||
return gzip.GzipFile.seek(self, offset)
|
||||
|
||||
# precision of os.utime() when restoring mbox timestamps
|
||||
utimes_precision = 5
|
||||
|
@ -548,40 +550,34 @@ class TestParseIMAPUrl(unittest.TestCase):
|
|||
archivemail.options.pwfile = None
|
||||
|
||||
urls_withoutpass = [
|
||||
('imaps://user@example.org@imap.example.org/upperbox/lowerbox',
|
||||
('user', None, 'example.org@imap.example.org',
|
||||
('imap://user@example.org@imap.example.org/upperbox/lowerbox',
|
||||
('user', None, 'example.org@imap.example.org', 143,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://"user@example.org"@imap.example.org/upperbox/lowerbox',
|
||||
('user@example.org', None, 'imap.example.org',
|
||||
('imap://"user@example.org"@imap.example.org/upperbox/lowerbox',
|
||||
('user@example.org', None, 'imap.example.org', 143,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://user@example.org"@imap.example.org/upperbox/lowerbox',
|
||||
('user', None, 'example.org"@imap.example.org',
|
||||
('imap://user@example.org"@imap.example.org/upperbox/lowerbox',
|
||||
('user', None, 'example.org"@imap.example.org', 143,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://"user@example.org@imap.example.org/upperbox/lowerbox',
|
||||
('"user', None, 'example.org@imap.example.org',
|
||||
('"user', None, 'example.org@imap.example.org', 993,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://"us\\"er@example.org"@imap.example.org/upperbox/lowerbox',
|
||||
('us"er@example.org', None, 'imap.example.org',
|
||||
('us"er@example.org', None, 'imap.example.org', 993,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://user\\@example.org@imap.example.org/upperbox/lowerbox',
|
||||
('user\\', None, 'example.org@imap.example.org',
|
||||
('user\\', None, 'example.org@imap.example.org', 993,
|
||||
'upperbox/lowerbox'))
|
||||
]
|
||||
urls_withpass = [
|
||||
('imaps://user@example.org:passwd@imap.example.org/upperbox/lowerbox',
|
||||
('user@example.org', 'passwd', 'imap.example.org',
|
||||
'upperbox/lowerbox'),
|
||||
('user', None, 'example.org:passwd@imap.example.org',
|
||||
('imap://user@example.org:passwd@imap.example.org/upperbox/lowerbox',
|
||||
('user@example.org', 'passwd', 'imap.example.org', 143,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://"user@example.org:passwd@imap.example.org/upperbox/lowerbox',
|
||||
('"user@example.org', "passwd", 'imap.example.org',
|
||||
'upperbox/lowerbox'),
|
||||
('"user', None, 'example.org:passwd@imap.example.org',
|
||||
('"user@example.org', "passwd", 'imap.example.org', 993,
|
||||
'upperbox/lowerbox')),
|
||||
('imaps://u\\ser\\@example.org:"p@sswd"@imap.example.org/upperbox/lowerbox',
|
||||
('u\\ser\\@example.org', 'p@sswd', 'imap.example.org',
|
||||
'upperbox/lowerbox'),
|
||||
('u\\ser\\', None, 'example.org:"p@sswd"@imap.example.org',
|
||||
('u\\ser\\@example.org', 'p@sswd', 'imap.example.org', 993,
|
||||
'upperbox/lowerbox'))
|
||||
]
|
||||
# These are invalid when the password's not stripped.
|
||||
|
@ -595,7 +591,7 @@ class TestParseIMAPUrl(unittest.TestCase):
|
|||
the URL, if present."""
|
||||
archivemail.options.pwfile = None
|
||||
for mbstr in self.urls_withpass + self.urls_withoutpass:
|
||||
url = mbstr[0][mbstr[0].find('://')+3:]
|
||||
url = mbstr[0]
|
||||
result = archivemail.parse_imap_url(url)
|
||||
self.assertEqual(result, mbstr[1])
|
||||
|
||||
|
@ -603,15 +599,24 @@ class TestParseIMAPUrl(unittest.TestCase):
|
|||
"""Parse test urls with --pwfile set. In this case the ':' character
|
||||
loses its meaning as a delimiter."""
|
||||
archivemail.options.pwfile = "whocares.txt"
|
||||
for mbstr in self.urls_withpass:
|
||||
url = mbstr[0][mbstr[0].find('://')+3:]
|
||||
result = archivemail.parse_imap_url(url)
|
||||
self.assertEqual(result, mbstr[2])
|
||||
for mbstr in self.urls_onlywithpass:
|
||||
url = mbstr[0][mbstr[0].find('://')+3:]
|
||||
url = mbstr[0]
|
||||
self.assertRaises(archivemail.UnexpectedError,
|
||||
archivemail.parse_imap_url, url)
|
||||
|
||||
def testUrlsDefaultPorts(self):
|
||||
"""If an IMAP URL does not specify a server port, the standard ports
|
||||
are used."""
|
||||
archivemail.options.pwfile = "doesnotexist.txt"
|
||||
self.assertEqual(143, archivemail.parse_imap_url("imap://user@host/box")[3])
|
||||
self.assertEqual(993, archivemail.parse_imap_url("imaps://user@host/box")[3])
|
||||
|
||||
def testUrlsWithPassAndPortnumber(self):
|
||||
"""IMAP URLs with an embedded password and a server port number are
|
||||
correctly parsed."""
|
||||
self.assertEqual(1234, archivemail.parse_imap_url("imap://user:pass@host:1234/box")[3])
|
||||
self.assertEqual(1234, archivemail.parse_imap_url("imap://user:pass@host:1234/box")[3])
|
||||
|
||||
def tearDown(self):
|
||||
archivemail.options.quiet = False
|
||||
archivemail.options.verbose = False
|
||||
|
@ -637,6 +642,27 @@ class TestIMAPQuoting(unittest.TestCase):
|
|||
self.assertEqual(unquoted, archivemail.imap_unquote(quoted))
|
||||
|
||||
|
||||
########## Modified UTF-7 support functions ##########
|
||||
|
||||
class TestModUTF7(unittest.TestCase):
|
||||
goodpairs = (
|
||||
(u"A\N{NOT IDENTICAL TO}A.", "A&ImI-A."),
|
||||
(u"Hi Mom -\N{WHITE SMILING FACE}-!", "Hi Mom -&Jjo--!"),
|
||||
(u"~peter/mail/\u53f0\u5317/\u65e5\u672c\u8a9e",
|
||||
"~peter/mail/&U,BTFw-/&ZeVnLIqe-")
|
||||
)
|
||||
|
||||
def testEncode(self):
|
||||
"""Ensure that encoding text in modified UTF-7 works properly."""
|
||||
for text, code in self.goodpairs:
|
||||
self.assertEqual(archivemail.mod_utf7_encode(text), code)
|
||||
|
||||
def testDecode(self):
|
||||
"""Ensure that decoding modified UTF-7 to text works properly."""
|
||||
for text, code in self.goodpairs:
|
||||
self.assertEqual(archivemail.mod_utf7_decode(code), text)
|
||||
|
||||
|
||||
########## acceptance testing ###########
|
||||
|
||||
class TestArchive(TestCaseInTempdir):
|
||||
|
|
Loading…
Reference in New Issue