Пример #1
0
def checkperms(state):
    for file in ALIASFILE, VIRTFILE:
        if state.VERBOSE:
            print C_('checking permissions on %(file)s')
        stat = None
        try:
            stat = os.stat(file)
        except OSError, e:
            if e.errno <> errno.ENOENT:
                raise
        if stat and (stat[ST_MODE] & targetmode) <> targetmode:
            state.ERRORS += 1
            octmode = oct(stat[ST_MODE])
            print C_('%(file)s permissions must be 0664 (got %(octmode)s)'),
            if state.FIX:
                print C_('(fixing)')
                os.chmod(file, stat[ST_MODE] | targetmode)
            else:
                print
        # Make sure the corresponding .db files are owned by the Mailman user.
        # We don't need to check the group ownership of the file, since
        # check_perms checks this itself.
        dbfile = file + '.db'
        stat = None
        try:
            stat = os.stat(dbfile)
        except OSError, e:
            if e.errno <> errno.ENOENT:
                raise
            continue
Пример #2
0
def fix_url(mlist, *args):
    try:
        opts, args = getopt.getopt(args, 'u:v', ['urlhost=', 'verbose'])
    except getopt.error as msg:
        usage(1, msg)

    verbose = 0
    urlhost = mailhost = None
    for opt, arg in opts:
        if opt in ('-u', '--urlhost'):
            urlhost = arg
        elif opt in ('-v', '--verbose'):
            verbose = 1

    # Make sure list is locked.
    if not mlist.Locked():
        if verbose:
            print(C_('Locking list'))
        mlist.Lock()
    if urlhost:
        web_page_url = mm_cfg.DEFAULT_URL_PATTERN % urlhost
        mailhost = mm_cfg.VIRTUAL_HOSTS.get(urlhost.lower(), urlhost)
    else:
        web_page_url = mm_cfg.DEFAULT_URL_PATTERN % mm_cfg.DEFAULT_URL_HOST
        mailhost = mm_cfg.DEFAULT_EMAIL_HOST

    if verbose:
        print(C_('Setting web_page_url to: %(web_page_url)s'))
    mlist.web_page_url = web_page_url
    if verbose:
        print(C_('Setting host_name to: %(mailhost)s'))
    mlist.host_name = mailhost
    print(C_('Saving list'))
    mlist.Save()
    mlist.Unlock()
    def __init__(self, basedir=None, reload=1, database=None):
        # If basedir isn't provided, assume the current directory
        if basedir is None:
            self.basedir = os.getcwd()
        else:
            basedir = os.path.expanduser(basedir)
            self.basedir = basedir
        self.database = database

        # If the directory doesn't exist, create it.  This code shouldn't get
        # run anymore, we create the directory in Archiver.py.  It should only
        # get used by legacy lists created that are only receiving their first
        # message in the HTML archive now -- Marc
        try:
            os.stat(self.basedir)
        except os.error as errdata:
            errno, errmsg = errdata
            if errno != 2:
                raise os.error(errdata)
            else:
                self.message(C_('Creating archive directory ') + self.basedir)
                omask = os.umask(0)
                try:
                    os.mkdir(self.basedir, self.DIRMODE)
                finally:
                    os.umask(omask)

        # Try to load previously pickled state
        try:
            if not reload:
                raise IOError
            f = open(os.path.join(self.basedir, 'pipermail.pck'), 'r')
            self.message(C_('Reloading pickled archive state'))
            d = pickle.load(f)
            f.close()
            for key, value in list(d.items()):
                setattr(self, key, value)
        except (IOError, EOFError):
            # No pickled version, so initialize various attributes
            self.archives = []  # Archives
            self._dirty_archives = []  # Archives that will have to be updated
            self.sequence = 0  # Sequence variable used for
            #   numbering articles
            self.update_TOC = 0  # Does the TOC need updating?
        #
        # make the basedir variable work when passed in as an __init__ arg
        # and different from the one in the pickle.  Let the one passed in
        # as an __init__ arg take precedence if it's stated.  This way, an
        # archive can be moved from one place to another and still work.
        #
        if basedir != self.basedir:
            self.basedir = basedir
Пример #4
0
def create(mlist, cgi=False, nolock=False, quiet=False):
    if mlist is None:
        return
    listname = mlist.internal_name()
    fieldsz = len(listname) + len('-unsubscribe')
    if cgi:
        # If a list is being created via the CGI, the best we can do is send
        # an email message to mailman-owner requesting that the proper aliases
        # be installed.
        sfp = StringIO()
        if not quiet:
            print(_("""
The mailing list `%(listname)s' has been created via the through-the-web
interface.  In order to complete the activation of this mailing list, the
proper /etc/aliases (or equivalent) file must be updated.  The program
`newaliases' may also have to be run.

Here are the entries for the /etc/aliases file:
"""),
                  file=sfp)
        outfp = sfp
    else:
        if not quiet:
            print(
                C_("""\
To finish creating your mailing list, you must edit your /etc/aliases (or
equivalent) file by adding the following lines, and possibly running the
`newaliases' program:
"""))
        print(C_("""\
## %(listname)s mailing list"""))
        outfp = sys.stdout
    # Common path
    for k, v in makealiases(listname):
        print(k + ':', ((fieldsz - len(k)) * ' '), v, file=outfp)
    # If we're using the command line interface, we're done.  For ttw, we need
    # to actually send the message to mailman-owner now.
    if not cgi:
        print(file=outfp)
        return
    # Send the message to the site -owner so someone can do something about
    # this request.
    siteowner = Utils.get_site_email(extra='owner')
    # Should this be sent in the site list's preferred language?
    msg = Message.UserNotification(
        siteowner, siteowner,
        _('Mailing list creation request for list %(listname)s'),
        sfp.getvalue(), mm_cfg.DEFAULT_SERVER_LANGUAGE)
    msg.send(mlist)
Пример #5
0
def checkperms(state):
    for file in ALIASFILE, VIRTFILE:
        if state.VERBOSE:
            print(C_('checking permissions on %(file)s'))
        stat = None
        try:
            stat = os.stat(file)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
        if stat and (stat[ST_MODE] & targetmode) != targetmode:
            state.ERRORS += 1
            octmode = oct(stat[ST_MODE])
            print(C_('%(file)s permissions must be 0664 (got %(octmode)s)'), end=' ')
            if state.FIX:
                print(C_('(fixing)'))
                os.chmod(file, stat[ST_MODE] | targetmode)
            else:
                print()
        # Make sure the corresponding .db files are owned by the Mailman user.
        # We don't need to check the group ownership of the file, since
        # check_perms checks this itself.
        dbfile = file + '.db'
        stat = None
        try:
            stat = os.stat(dbfile)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
            continue
        if state.VERBOSE:
            print(C_('checking ownership of %(dbfile)s'))
        user = mm_cfg.MAILMAN_USER
        ownerok = stat[ST_UID] == pwd.getpwnam(user)[2]
        if not ownerok:
            try:
                owner = pwd.getpwuid(stat[ST_UID])[0]
            except KeyError:
                owner = 'uid %d' % stat[ST_UID]
            print(C_(
                '%(dbfile)s owned by %(owner)s (must be owned by %(user)s'), end=' ')
            state.ERRORS += 1
            if state.FIX:
                print(C_('(fixing)'))
                uid = pwd.getpwnam(user)[2]
                gid = grp.getgrnam(mm_cfg.MAILMAN_GROUP)[2]
                os.chown(dbfile, uid, gid)
            else:
                print()
        if stat and (stat[ST_MODE] & targetmode) != targetmode:
            state.ERRORS += 1
            octmode = oct(stat[ST_MODE])
            print(C_('%(dbfile)s permissions must be 0664 (got %(octmode)s)'), end=' ')
            if state.FIX:
                print(C_('(fixing)'))
                os.chmod(dbfile, stat[ST_MODE] | targetmode)
            else:
                print()
Пример #6
0
def usage(code, msg=''):
    if code:
        fd = sys.stderr
    else:
        fd = sys.stdout
    print(C_(__doc__.replace('%', '%%')), file=fd)
    if msg:
        print(msg, file=fd)
    sys.exit(code)
Пример #7
0
def usage(code, msg=''):
    if code:
        fd = sys.stderr
    else:
        fd = sys.stdout
    print >> fd, C_(__doc__.replace('%', '%%'))
    if msg:
        print >> fd, msg
    sys.exit(code)
    def update_archive(self, archive):
        self.archive = archive
        self.message(C_("Updating index files for archive [%(archive)s]"))
        arcdir = os.path.join(self.basedir, archive)
        self.__set_parameters(archive)

        for hdr in ('Date', 'Subject', 'Author'):
            self._update_simple_index(hdr, archive, arcdir)

        self._update_thread_index(archive, arcdir)
Пример #9
0
def convert(mlist):
    for attr in ('msg_header', 'msg_footer', 'digest_header', 'digest_footer',
                 'autoresponse_postings_text', 'autoresponse_admin_text',
                 'autoresponse_request_text'):
        s = getattr(mlist, attr)
        t = Utils.to_dollar(s)
        setattr(mlist, attr, t)
    mlist.use_dollar_strings = 1
    print(C_('Saving list'))
    mlist.Save()
Пример #10
0
def reset_pw(mlist, *args):
    try:
        opts, args = getopt.getopt(args, 'v', ['verbose'])
    except getopt.error as msg:
        usage(1, msg)

    verbose = False
    for opt, args in opts:
        if opt in ('-v', '--verbose'):
            verbose = True

    listname = mlist.internal_name()
    if verbose:
        print(C_('Changing passwords for list: %(listname)s'))

    for member in mlist.getMembers():
        randompw = Utils.MakeRandomPassword()
        mlist.setMemberPassword(member, randompw)
        if verbose:
            print(C_('New password for member %(member)40s: %(randompw)s'))

    mlist.Save()
    def _update_thread_index(self, archive, arcdir):
        self.message(C_("  Thread"))
        self._open_index_file_as_stdout(arcdir, "thread")
        self.type = 'Thread'
        self.write_index_header()

        # To handle the prev./next in thread pointers, we need to
        # track articles 5 at a time.

        # Get the first 5 articles
        L = [None] * 5
        i = 2
        msgid = self.database.first(self.archive, 'thread')

        while msgid is not None and i < 5:
            L[i] = self.database.getArticle(self.archive, msgid)
            i = i + 1
            msgid = self.database.next(self.archive, 'thread')

        while L[2] is not None:
            article = L[2]
            artkey = None
            if article is not None:
                artkey = article.threadKey
            if artkey is not None:
                self.write_threadindex_entry(article, artkey.count('-') - 1)
                if (archive, article.msgid) in self.database.changed:
                    a1 = L[1]
                    a3 = L[3]
                    self.update_article(arcdir, article, a1, a3)
                    if a3 is not None:
                        self.database.changed[(archive, a3.msgid)] = None
                    if a1 is not None:
                        key = archive, a1.msgid
                        if key not in self.database.changed:
                            self.update_article(arcdir, a1, L[0], L[2])
                        else:
                            del self.database.changed[key]
            if L[0]:
                L[0].finished_update_article()
            L = L[1:]  # Rotate the list
            if msgid is None:
                L.append(msgid)
            else:
                L.append(self.database.getArticle(self.archive, msgid))
            msgid = self.database.next(self.archive, 'thread')

        self.write_index_footer()
        self._restore_stdout()
Пример #12
0
 def dump(self, listnames, password_scheme):
     print >> self._fp, '<?xml version="1.0" encoding="UTF-8"?>'
     self._push_element(
         'mailman', **{
             'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
             'xsi:noNamespaceSchemaLocation': 'ssi-1.0.xsd',
         })
     for listname in sorted(listnames):
         try:
             mlist = MailList(listname, lock=False)
         except Errors.MMUnknownListError:
             print >> sys.stderr, C_('No such list: %(listname)s')
             continue
         self._dump_list(mlist, password_scheme)
     self._pop_element('mailman')
Пример #13
0
def parseargs():
    parser = optparse.OptionParser(version=mm_cfg.VERSION,
                                   usage=C_("""\
%%prog [options]

Export the configuration and members of a mailing list in XML format."""))
    parser.add_option('-o',
                      '--outputfile',
                      metavar='FILENAME',
                      default=None,
                      type='string',
                      help=C_("""\
Output XML to FILENAME.  If not given, or if FILENAME is '-', standard out is
used."""))
    parser.add_option('-p',
                      '--password-scheme',
                      default='none',
                      type='string',
                      help=C_("""\
Specify the RFC 2307 style hashing scheme for passwords included in the
output.  Use -P to get a list of supported schemes, which are
case-insensitive."""))
    parser.add_option('-P',
                      '--list-hash-schemes',
                      default=False,
                      action='store_true',
                      help=C_("""\
List the supported password hashing schemes and exit.  The scheme labels are
case-insensitive."""))
    parser.add_option('-l',
                      '--listname',
                      default=[],
                      action='append',
                      type='string',
                      metavar='LISTNAME',
                      dest='listnames',
                      help=C_("""\
The list to include in the output.  If not given, then all mailing lists are
included in the XML output.  Multiple -l flags may be given."""))
    opts, args = parser.parse_args()
    if args:
        parser.print_help()
        parser.error(C_('Unexpected arguments'))
    if opts.list_hash_schemes:
        for label in SCHEMES:
            print label.upper()
        sys.exit(0)
    if opts.password_scheme.lower() not in SCHEMES:
        parser.error(C_('Invalid password scheme'))
    return parser, opts, args
Пример #14
0
def remove(mlist, cgi=False):
    listname = mlist.internal_name()
    fieldsz = len(listname) + len('-unsubscribe')
    if cgi:
        # If a list is being removed via the CGI, the best we can do is send
        # an email message to mailman-owner requesting that the appropriate
        # aliases be deleted.
        sfp = StringIO()
        print(_("""\
The mailing list `%(listname)s' has been removed via the through-the-web
interface.  In order to complete the de-activation of this mailing list, the
appropriate /etc/aliases (or equivalent) file must be updated.  The program
`newaliases' may also have to be run.

Here are the entries in the /etc/aliases file that should be removed:
"""),
              file=sfp)
        outfp = sfp
    else:
        print(
            C_("""
To finish removing your mailing list, you must edit your /etc/aliases (or
equivalent) file by removing the following lines, and possibly running the
`newaliases' program:

## %(listname)s mailing list"""))
        outfp = sys.stdout
    # Common path
    for k, v in makealiases(listname):
        print(k + ':', ((fieldsz - len(k)) * ' '), v, file=outfp)
    # If we're using the command line interface, we're done.  For ttw, we need
    # to actually send the message to mailman-owner now.
    if not cgi:
        print(file=outfp)
        return
    siteowner = Utils.get_site_email(extra='owner')
    # Should this be sent in the site list's preferred language?
    msg = Message.UserNotification(
        siteowner, siteowner,
        _('Mailing list removal request for list %(listname)s'),
        sfp.getvalue(), mm_cfg.DEFAULT_SERVER_LANGUAGE)
    msg['Date'] = email.utils.formatdate(localtime=1)
    outq = get_switchboard(mm_cfg.OUTQUEUE_DIR)
    outq.enqueue(msg, recips=[siteowner], nodecorate=1)
    def close(self):
        "Close an archive, save its state, and update any changed archives."
        self.update_dirty_archives()
        self.update_TOC = 0
        self.write_TOC()
        # Save the collective state
        self.message(
            C_('Pickling archive state into ') +
            os.path.join(self.basedir, 'pipermail.pck'))
        self.database.close()
        del self.database

        omask = os.umask(0o07)
        try:
            f = open(os.path.join(self.basedir, 'pipermail.pck'), 'wb')
        finally:
            os.umask(omask)
        pickle.dump(self.getstate(), f)
        f.close()
 def processUnixMailbox(self, input, start=None, end=None):
     mbox = ArchiverMailbox(input, self.maillist)
     if start is None:
         start = 0
     counter = 0
     if start:
         mbox.skipping(True)
     while counter < start:
         try:
             m = next(mbox)
         except Errors.DiscardMessage:
             continue
         if m is None:
             return
         counter += 1
     if start:
         mbox.skipping(False)
     while 1:
         try:
             pos = input.tell()
             m = next(mbox)
         except Errors.DiscardMessage:
             continue
         except Exception:
             syslog('error', 'uncaught archiver exception at filepos: %s',
                    pos)
             raise
         if m is None:
             break
         if m == '':
             # It was an unparseable message
             continue
         msgid = m.get('message-id', 'n/a')
         self.message(C_('#%(counter)05d %(msgid)s'))
         a = self._makeArticle(m, self.sequence)
         self.sequence += 1
         self.add_article(a)
         if end is not None and counter >= end:
             break
         counter += 1
Пример #17
0
        opts, args = getopt.getopt(args, 'u:v',
                                   ['from-is-list-value=', 'verbose'])
    except getopt.error, msg:
        usage(1, msg)

    verbose = 0
    f_value = 0
    for opt, arg in opts:
        if opt in ('-u', '--from-is-list-value'):
            f_value = int(arg)
        elif opt in ('-v', '--verbose'):
            verbose = 1

    # Make sure list is locked.
    if not mlist.Locked():
        if verbose:
            print C_('Locking list')
        mlist.Lock()

    if verbose:
        old_f_value = mlist.from_is_list
        print C_('Setting from_is_list from: %(old_f_value)s to: %(f_value)s')
    mlist.from_is_list = f_value
    print C_('Saving list')
    mlist.Save()
    mlist.Unlock()


if __name__ == '__main__':
    usage(0)
Пример #18
0
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

"""Convert a list's interpolation strings from %-strings to $-strings.

This script is intended to be run as a bin/withlist script, i.e.

% bin/withlist -l -r convert <mylist>
"""

import paths
from Mailman import Utils
from Mailman.i18n import C_

def convert(mlist):
    for attr in ('msg_header', 'msg_footer', 'digest_header', 'digest_footer',
                 'autoresponse_postings_text', 'autoresponse_admin_text',
                 'autoresponse_request_text'):
        s = getattr(mlist, attr)
        t = Utils.to_dollar(s)
        setattr(mlist, attr, t)
    mlist.use_dollar_strings = 1
    print(C_('Saving list'))
    mlist.Save()



if __name__ == '__main__':
    print(C_(__doc__.replace('%', '%%')))
Пример #19
0
def usage(code, msg=''):
    print C_(__doc__.replace('%', '%%'))
    if msg:
        print msg
    sys.exit(code)
Пример #20
0
        opts, args = getopt.getopt(args, 'u:v', ['urlhost=', 'verbose'])
    except getopt.error, msg:
        usage(1, msg)

    verbose = 0
    urlhost = mailhost = None
    for opt, arg in opts:
        if opt in ('-u', '--urlhost'):
            urlhost = arg
        elif opt in ('-v', '--verbose'):
            verbose = 1

    # Make sure list is locked.
    if not mlist.Locked():
        if verbose:
            print C_('Locking list')
        mlist.Lock()
    if urlhost:
        web_page_url = mm_cfg.DEFAULT_URL_PATTERN % urlhost
        mailhost = mm_cfg.VIRTUAL_HOSTS.get(urlhost.lower(), urlhost)
    else:
        web_page_url = mm_cfg.DEFAULT_URL_PATTERN % mm_cfg.DEFAULT_URL_HOST
        mailhost = mm_cfg.DEFAULT_EMAIL_HOST

    if verbose:
        print C_('Setting web_page_url to: %(web_page_url)s')
    mlist.web_page_url = web_page_url
    if verbose:
        print C_('Setting host_name to: %(mailhost)s')
    mlist.host_name = mailhost
    print C_('Saving list')
Пример #21
0
         os.chmod(file, stat[ST_MODE] | targetmode)
     else:
         print
 # Make sure the corresponding .db files are owned by the Mailman user.
 # We don't need to check the group ownership of the file, since
 # check_perms checks this itself.
 dbfile = file + '.db'
 stat = None
 try:
     stat = os.stat(dbfile)
 except OSError, e:
     if e.errno <> errno.ENOENT:
         raise
     continue
 if state.VERBOSE:
     print C_('checking ownership of %(dbfile)s')
 user = mm_cfg.MAILMAN_USER
 ownerok = stat[ST_UID] == pwd.getpwnam(user)[2]
 if not ownerok:
     try:
         owner = pwd.getpwuid(stat[ST_UID])[0]
     except KeyError:
         owner = 'uid %d' % stat[ST_UID]
     print C_(
         '%(dbfile)s owned by %(owner)s (must be owned by %(user)s'),
     state.ERRORS += 1
     if state.FIX:
         print C_('(fixing)')
         uid = pwd.getpwnam(user)[2]
         gid = grp.getgrnam(mm_cfg.MAILMAN_GROUP)[2]
         os.chown(dbfile, uid, gid)
Пример #22
0
        print >> fd, msg
    sys.exit(code)


def reset_pw(mlist, *args):
    try:
        opts, args = getopt.getopt(args, 'v', ['verbose'])
    except getopt.error, msg:
        usage(1, msg)

    verbose = False
    for opt, args in opts:
        if opt in ('-v', '--verbose'):
            verbose = True

    listname = mlist.internal_name()
    if verbose:
        print C_('Changing passwords for list: %(listname)s')

    for member in mlist.getMembers():
        randompw = Utils.MakeRandomPassword()
        mlist.setMemberPassword(member, randompw)
        if verbose:
            print C_('New password for member %(member)40s: %(randompw)s')

    mlist.Save()


if __name__ == '__main__':
    usage(0)