1# Copyright (c) 2012 Ian C. Good 2# 3# Permission is hereby granted, free of charge, to any person obtaining a copy 4# of this software and associated documentation files (the "Software"), to deal 5# in the Software without restriction, including without limitation the rights 6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7# copies of the Software, and to permit persons to whom the Software is 8# furnished to do so, subject to the following conditions: 9# 10# The above copyright notice and this permission notice shall be included in 11# all copies or substantial portions of the Software. 12# 13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19# THE SOFTWARE. 20# 21 22"""Implements a simple forwarding policy, to transform or replace 23recipients. 24 25""" 26 27from __future__ import absolute_import 28 29import re 30 31from . import QueuePolicy 32 33__all__ = ['Forward'] 34 35 36class Forward(QueuePolicy): 37 """Each |Envelope| recipient is run through :func:`re.sub()` to see if it 38 is modified. If a recipient matches a mapping rule, no further mapping 39 rules are processed. Mapping rules are checked in the order that they were 40 added. 41 42 """ 43 44 def __init__(self): 45 self.mapping = [] 46 47 def add_mapping(self, pattern, repl, count=0): 48 """Adds a mapping rule. 49 50 :param pattern: Pattern to check recipient against. 51 :type pattern: :py:obj:`str` or :class:`re.RegexObject` 52 :param repl: Replacement for ``pattern`` matches, as described by 53 :func:`re.sub()`. 54 :type repl: :py:obj:`str` or function 55 :param count: Max number of replacements per recipient string. 56 57 """ 58 self.mapping.append((re.compile(pattern), repl, count)) 59 60 def apply(self, envelope): 61 n_rcpt = len(envelope.recipients) 62 for i in range(n_rcpt): 63 old_rcpt = envelope.recipients[i] 64 for pattern, repl, count in self.mapping: 65 new_rcpt, changes = re.subn(pattern, repl, old_rcpt, count) 66 if new_rcpt and changes > 0: 67 envelope.recipients[i] = new_rcpt 68 break 69 70 71# vim:et:fdm=marker:sts=4:sw=4:ts=4 72