Beispiel #1
0
	def doit (self, isPost):
		(path, query, body) = self.startup (isPost)
		if path == '/ping':
			self.ok ('pong')
		else:
			if path == '/is_no_systemmail':
				mode = 0
			elif path == '/filter_or_forward':
				mode = 1
			elif path == '/scan_and_unsubscribe':
				mode = 2
			else:
				mode = -1
			if mode != -1:
				if body:
					msg = email.message_from_string (body)
					bav = BAV (msg, mode)
					if bav.execute ():
						self.ok (bav.reason)
					else:
						self.err (bav.reason)
				else:
					agn.log (agn.LV_ERROR, 'doit', 'No body for path %s found' % path)
					self.err ('%s is only allowed using POST' % path)
			else:
				agn.log (agn.LV_WARNING, 'doit', 'Invalid command/path ' + self.path)
				self.err ('Not (yet) implemented')
Beispiel #2
0
 def readConfiguration(self):
     config = None
     db = eagn.DB()
     try:
         if db.isopen():
             config = (db.cursor.stream(
                 'SELECT name, value FROM config_tbl WHERE class = :class',
                 {
                     'class': 'generate'
                 }).filter(lambda nv: nv[0] is not None).dict())
         else:
             raise agn.error('access to database: %s' % db.lastError())
     except Exception as e:
         agn.log(agn.LV_ERROR, 'sched',
                 'Failed to read configuration: %s' % e)
     finally:
         db.done()
     if config is not None:
         self.config = config
         self.companies = self.configuration(
             'companies', convert=lambda v: agn.Stream.ifelse(agn.Range(v)))
         if self.companies:
             agn.log(
                 agn.LV_INFO, 'sched',
                 'Limit operations on these companies: %s' % self.companies)
Beispiel #3
0
 def moveTo(self, dest):
     try:
         shutil.move(self.path, dest)
         agn.log(agn.LV_DEBUG, "block", "Moved %s to %s" % (self.path, dest))
         return True
     except OSError, e:
         agn.log(agn.LV_ERROR, "block", "Failed to move %s to %s %s" % (self.path, dest, ` e.args `))
Beispiel #4
0
 def __init__(self, cfg=None, full=False, prefix='xmlrpc', timeout=None):
     self.term = False
     host = ''
     port = 8080
     allowNone = False
     serverClass = XMLRPC.XMLRPCServer
     if not cfg is None:
         host = cfg.get('%s.host' % prefix, host)
         port = cfg.iget('%s.port' % prefix, port)
         allowNone = cfg.bget('%s.allow_none' % prefix, allowNone)
         server = cfg.get('%s.server' % prefix, None)
         if server is not None:
             if server == 'forking':
                 serverClass = XMLRPC.XMLRPCServerForking
             elif server == 'threading':
                 serverClass = XMLRPC.XMLRPCServerThreading
             else:
                 agn.log(
                     agn.LV_WARNING, 'xmlrpc',
                     'Requested unknown server type %s, fallback to simple server'
                     % server)
     if full:
         self.__setupSignals()
     self.server = serverClass(port, host, timeout, allowNone)
     self.server.register_introspection_functions()
     self.server.register_multicall_functions()
Beispiel #5
0
	def pendings (self):
		while self.pending.running:
			w = self.wait ()
			if w is None:
				break
			agn.log (agn.LV_DEBUG, 'par', '%s: process finished' % w.description)
		while self.pending.queued and len (self.pending.running) < self.processes:
			prio = agn.Stream.of (self.pending.queued.keys ()).sorted ().first ()
			w = self.pending.queued[prio].pop (0)
			if not self.pending.queued[prio]:
				del self.pending.queued[prio]
			#
			if w.prepare is not None:
				try:
					w.prepare (*w.args, **w.kws)
				except Exception as e:
					agn.logexc (agn.LV_ERROR, 'par', '%s: prepare fails: %s' % (w.description, e))
			def starter ():
				self.processtitle (w.description)
				rc = w.method (*w.args, **w.kws)
				self.processtitle ()
				return rc
			w.pid = self.pending.control.spawn (starter)
			self.pending.running.append (w)
			agn.log (agn.LV_DEBUG, 'par', '%s: launched' % w.description)
		return self.pending.running or self.pending.queued
Beispiel #6
0
	def lock (self, key):
		try:
			self.locks[key] += 1
			agn.log (agn.LV_DEBUG, 'lock', '%r increased' % key)
		except KeyError:
			self.locks[key] = 1
			agn.log (agn.LV_DEBUG, 'lock', '%r set' % key)
Beispiel #7
0
def main():
    global upgrade
    pid = -1
    ips = ['127.0.0.1']
    opts = getopt.getopt(sys.argv[1:], 'i:')
    for opt in opts[0]:
        if opt[0] == '-i':
            ips.append(opt[1])
    agn.lockpath = '/var/tmp'
    agn.lock()
    pid = os.fork()
    if pid == 0:
        upgrade = None
        set_signals(updhandler)
        upgrade = Upgrade()
        upgrade.start()
    else:
        agn.log(agn.LV_INFO, 'upgrade', 'Starting up')
        set_signals(webhandler)
        server = Server(None)
        while not term:
            server.handle_request()
        time.sleep(2)
        if pid > 0:
            os.kill(pid, signal.SIGTERM)
        try:
            os.unlink(datafile)
        except OSError, e:
            agn.log(
                agn.LV_ERROR, 'upgrade',
                'Failed to remove datafile %s: %s' % (datafile, repr(e.args)))
Beispiel #8
0
	def __init__ (self, msg, mode):
		global	rules, rlock

		self.msg = msg
		self.mode = mode
		self.parm = {}
		if not self.msg.has_key (BAV.x_agn):
			if self.msg.has_key ('return-path'):
				rp = self.msg['return-path'].strip ()
				if rp[0] == '<' and rp[-1] == '>':
					addr = rp[1:-1].lower ()
					try:
						fd = open (BAV.configFile)
						for line in [l for l in fd if len (l) > 0 and l[0] != '#']:
							parts = line.split (None, 1)
							if parts[0].lower () == addr:
								data = agn.chop (parts[1])
								if data[:7] == 'accept:':
									self.msg[BAV.x_agn] = data[7:]
								break
						fd.close ()
					except IOError, e:
						agn.log (agn.LV_WARNING, 'bav', 'Cannot read file %s %s' % (BAV.configFile, `e.args`))
			else:
				agn.log (agn.LV_WARNING, 'bav', 'No %s header, neither Return-Path: found' % BAV.x_agn)
Beispiel #9
0
 def __cdo(self, collection, query, data, filler, what, cursor=None):  #{{{
     for (key, companies) in collection.items():
         if data:
             ndata = data.copy()
         else:
             ndata = {}
         if callable(query):
             basequery = query(key)
         else:
             basequery = key
         filler(ndata, key)
         if basequery is not None:
             companies = sorted(companies)
             while companies:
                 chunk = companies[:20]
                 companies = companies[20:]
                 if len(chunk) > 1:
                     nquery = '%s IN (%s)' % (basequery, ', '.join(
                         [str(_c) for _c in chunk]))
                 else:
                     nquery = '%s = %d' % (basequery, chunk[0])
                 self.__do(
                     nquery, ndata, '%s for %s' %
                     (what, ', '.join([str(_c) for _c in chunk])), cursor)
         else:
             agn.log(agn.LV_INFO, 'cdo',
                     'Skip execution for key %r' % (key, ))
Beispiel #10
0
	def writeFile (self):
		if self.armid:
			if os.path.isfile (self.fname):
				try:
					os.unlink (self.fname)
				except OSError, e:
					agn.log (agn.LV_ERROR, 'auto', 'Unable to remove file %s: %s' % (self.fname, str (e)))
	def readMailertable (self):
		self.domains = []
		self.mtdom = {}

		if self.sendmailFree:
			self.domains = [self.fixdomain]
			me = socket.getfqdn ()
			if me:
				self.domains.append (me)
			db = agn.DBaseID ()
			if not db is None:
				c = db.cursor ()
				if not c is None:
					for r in c.query ('SELECT mailloop_domain FROM company_tbl'):
						if r[0] and not r[0] in self.domains:
							self.domains.append (r[0])
					c.close ()
				db.close ()
			return
		try:
			for line in fileReader (mailBase + '/mailertable'):
				parts = line.split ()
				if len (parts) > 0 and parts[0][0] != '.':
					self.domains.append (parts[0])
					self.mtdom[parts[0]] = 0
		except IOError, e:
			agn.log (agn.LV_ERROR, 'data', 'Unable to read mailertable %s' % `e.args`)
Beispiel #12
0
	def unsubscribe (self, customerID, mailingID):
		db = agn.DBaseID ()
		if db is not None:
			cursor = db.cursor ()
			if cursor is not None:
				rq = cursor.querys ('SELECT mailinglist_id, company_id FROM mailing_tbl WHERE mailing_id = :mailingID', {'mailingID': mailingID})
				if rq is not None:
					mailinglistID = rq[0]
					companyID = rq[1]
					query = cursor.rselect ('UPDATE customer_%d_binding_tbl SET user_status = :userStatus, user_remark = :userRemark, timestamp = %%(sysdate)s, exit_mailing_id = :mailingID WHERE customer_id = :customerID AND mailinglist_id = :mailinglistID' % companyID)
					data = {
						'userStatus': agn.UserStatus.ADMOUT,
						'userRemark': 'Opt-out by mandatory CSA link (mailto)',
						'mailingID': mailingID,
						'customerID': customerID,
						'mailinglistID': mailinglistID
					}
					cnt = cursor.update (query, data)
					if cnt == 1:
						agn.log (agn.LV_INFO, 'unsub', 'Unsubscribed customer %d for company %d on mailinglist %d due to mailing %d' % (customerID, companyID, mailinglistID, mailingID))
					else:
						agn.log (agn.LV_WARNING, 'unsub', 'Failed to unsubscribe customer %d for company %d on mailinglist %d due to mailing %d, matching %d rows (expected one row)' % (customerID, companyID, mailinglistID, mailingID, cnt))
					cursor.sync ()
				else:
					agn.log (agn.LV_WARNING, 'unsub', 'No mailinglist for mailing %d found, do not unsubscribe %d' % (mailingID, customerID))
				cursor.close ()
			else:
				agn.log (agn.LV_ERROR, 'unsub', 'Failed to open database: %s' % db.lastError ())
			db.close ()
		else:
			agn.log (agn.LV_ERROR, 'unsub', 'Failed to setup database interface')
Beispiel #13
0
 def wait(self, block=False):
     w = None
     while self.pending.running and w is None:
         rc = self.pending.control.join(block=block)
         if not rc.pid:
             break
         #
         w = (agn.Stream.of(
             self.pending.running).filter(lambda r: r.pid == rc.pid).first(
                 no=None))
         if w is not None:
             agn.log(
                 agn.LV_DEBUG, 'par', '%s: returned with %s' %
                 (w.description,
                  ('exit with %d' %
                   rc.exitcode) if rc.exitcode is not None else
                  ('died due to signal %d' % rc.signal)))
             if w.finalize is not None:
                 try:
                     w.finalize(rc, *w.args, **w.kws)
                 except Exception as e:
                     agn.logexc(
                         agn.LV_ERROR, 'per',
                         '%s: finalize fails: %s' % (w.description, e))
             self.pending.running.remove(w)
             self.lockTitle()
     return w
Beispiel #14
0
	def removeFile (self):
		for fname in self.fname, self.limit:
			if os.path.isfile (fname):
				try:
					os.unlink (fname)
				except OSError, e:
					agn.log (agn.LV_ERROR, 'auto', 'Unable to remove file %s: %s' % (fname, str (e)))
Beispiel #15
0
def main():
	global upgrade
	pid = -1
	ips = ['127.0.0.1']
	opts = getopt.getopt (sys.argv[1:], 'i:')
	for opt in opts[0]:
		if opt[0] == '-i':
			ips.append (opt[1])
	agn.lockpath = '/var/tmp'
	agn.lock ()
	pid = os.fork ()
	if pid == 0:
		upgrade = None
		set_signals(updhandler)
		upgrade = Upgrade()
		upgrade.start()
	else:
		agn.log (agn.LV_INFO, 'upgrade', 'Starting up')
		set_signals(webhandler)
		server = Server(None)
		while not term:
			server.handle_request()
		time.sleep (2)
		if pid > 0:
			os.kill(pid, signal.SIGTERM)
		try:
			os.unlink(datafile)
		except OSError, e:
			agn.log(agn.LV_ERROR, 'upgrade', 'Failed to remove datafile %s: %s' % (datafile, repr(e.args)))
Beispiel #16
0
	def execute_filter_or_forward (self):
		match = self.rule.matchHeader (self.msg, 'filter')
		if not match is None and not match[1].inverse:
			if not match[1].parm:
				parm = 'save'
			else:
				parm = match[1].parm
		else:
			parm = 'sent'
		self.saveMessage (parm)
		if parm == 'sent':
			while self.msg.has_key (BAV.x_agn):
				del self.msg[BAV.x_agn]
			if self.parm.has_key ('fwd'):

				sendMsg = self.msg
				self.sendmail (sendMsg, self.parm['fwd'])
			if self.parm.has_key ('ar'):
				ar = self.parm['ar']
				if self.parm.has_key ('from') and not self.headerFrom is None and not self.headerFrom[1]:
					sender = self.headerFrom[1]
					ar = Autoresponder (ar, sender)
					nmsg = ar.createMessage (self.msg, self.parm)
					if nmsg:
						agn.log (agn.LV_INFO, 'fof', 'Forward newly generated message to %s' % sender)
						self.sendmail (nmsg, sender)
				else:
					agn.log (agn.LV_INFO, 'fof', 'No sender in original message found')
			if self.parm.has_key ('sub') and self.parm.has_key ('cid') and self.parm.has_key ('from'):
				(mlist, form) = self.parm['sub'].split (':', 1)
				cid = self.parm['cid']
				if self.headerFrom and self.headerFrom[1]:
					self.subscribe (self.headerFrom[1].lower (), self.headerFrom[0], int (cid), int (mlist), int (form))
		return True
Beispiel #17
0
	def updateRules (self, rules):
		inuse = set ()
		globalRule = None
		for (rid, rule) in rules.items ():
			if globalRule is None:
				try:
					fd = open (self.ruleFile)
					globalRule = fd.read ()
					fd.close ()
					if not globalRule.endswith ('\n'):
						globalRule += '\n'
				except IOError as e:
					agn.log (agn.LV_ERROR, 'rule', 'Failed to open "%s" for reading: %s' % (self.ruleFile, str (e)))
			inuse.add (rid)
			fname = self.ruleFormat % rid
			try:
				fd = open (fname, 'w')
				if globalRule:
					fd.write (globalRule)
				for sect in sorted (rule):
					fd.write ('[%s]\n' % agn.toutf8 (sect))
					for line in rule[sect]:
						fd.write ('%s\n' % agn.toutf8 (line))
				fd.close ()
			except IOError, e:
				agn.log (agn.LV_ERROR, 'rule', 'Failed to open "%s" for writing: %r' % (fname, e.args))
	def __init__ (self):
		self.fixdomain = 'localhost'
		self.domains = []
		self.prefix = 'ext_'
		self.last = None
		self.autoresponder = []
		self.mtdom = {}

		self.sendmailFree = False
		if agn.iswin:
			self.sendmailFree = True
		else:
			if not smenable is None:
				sm = smenable.SMCtrl ()
				if sm.valid and not sm.enabled ():
					self.sendmailFree = True
				sm.done ()
		self.readMailertable ()
		try:
			files = os.listdir (arDirectory)
			for fname in files:
				if len (fname) > 8 and fname[:3] == 'ar_' and fname[-5:] == '.mail':
					rid = fname[3:-5]
					self.autoresponder.append (Autoresponder (rid, 0, None, None, None, None))
		except OSError, e:
			agn.log (agn.LV_ERROR, 'data', 'Unable to read directory %s %s' % (arDirectory, `e.args`))
Beispiel #19
0
 def isActive(self):
     rc = False
     reason = []
     proc = eagn.Processtable()
     be = proc.select(user='******',
                      comm='java',
                      rcmd='org.agnitas.backend.MailoutServerXMLRPC')
     if len(be) == 1:
         err = self.__stateCheck(be[0])
         if err is None:
             rc = True
         else:
             reason.append('Backend: %s' % err)
     elif len(be) > 1:
         reason.append('There are more than one backend running: %s' %
                       ', '.join([str(_t.pid) for _t in be]))
     else:
         reason.append('No java process is active')
     if not rc:
         agn.log(agn.LV_WARNING, 'active',
                 'Backend activity error: %s' % ', '.join(reason))
     elif reason:
         agn.log(agn.LV_INFO, 'active',
                 'Backend is active: %s' % ', '.join(reason))
     return rc
Beispiel #20
0
	def moveTo (self, dest):
		try:
			shutil.move (self.path, dest)
			agn.log (agn.LV_DEBUG, 'block', 'Moved %s to %s' % (self.path, dest))
			return True
		except OSError, e:
			agn.log (agn.LV_ERROR, 'block', 'Failed to move %s to %s %s' % (self.path, dest, `e.args`))
Beispiel #21
0
def main ():
	global	running, reread

	delay = 180
	(opts, param) = getopt.getopt (sys.argv[1:], 'vd:')
	for opt in opts:
		if opt[0] == '-v':
			agn.outlevel = agn.LV_DEBUG
			agn.outstream = sys.stderr
		elif opt[0] == '-d':
			delay = int (opt[1])

	signal.signal (signal.SIGINT, handler)
	signal.signal (signal.SIGTERM, handler)
	signal.signal (signal.SIGUSR1, handler)
	signal.signal (signal.SIGHUP, signal.SIG_IGN)
	signal.signal (signal.SIGPIPE, signal.SIG_IGN)
	agn.lock ()
	agn.log (agn.LV_INFO, 'main', 'Starting up')
	data = Data ()
	while running:
		forcedUpdate = reread
		reread = False
		data.update (forcedUpdate)
		n = delay
		while n > 0 and running and not reread:
			time.sleep (1)
			n -= 1
	data.done ()
	agn.log (agn.LV_INFO, 'main', 'Going down')
	agn.unlock ()
Beispiel #22
0
	def scan (self):
		files = sorted (os.listdir (self.incoming))
		for fname in [_f for _f in files if _f.endswith ('.final')]:
			basename = fname.split ('.')[0]
			if '%s.xml.gz' % basename in files and '%s.stamp' % basename in files:
				agn.log (agn.LV_INFO, 'scan', 'Found %s to process' % fname)
				self.doit (basename)
Beispiel #23
0
 def doit(self, isPost):
     (path, query, body) = self.startup(isPost)
     if path == '/ping':
         self.ok('pong')
     else:
         if path == '/is_no_systemmail':
             mode = 0
         elif path == '/filter_or_forward':
             mode = 1
         elif path == '/scan_and_unsubscribe':
             mode = 2
         else:
             mode = -1
         if mode != -1:
             if body:
                 msg = email.message_from_string(body)
                 bav = BAV(msg, mode)
                 if bav.execute():
                     self.ok(bav.reason)
                 else:
                     self.err(bav.reason)
             else:
                 agn.log(agn.LV_ERROR, 'doit',
                         'No body for path %s found' % path)
                 self.err('%s is only allowed using POST' % path)
         else:
             agn.log(agn.LV_WARNING, 'doit',
                     'Invalid command/path ' + self.path)
             self.err('Not (yet) implemented')
Beispiel #24
0
	def __init__ (self, raw, msg, mode, dryrun = False):
		self.raw = raw
		self.msg = msg
		self.mode = mode
		self.dryrun = dryrun
		self.parsedEMail = eagn.ParseEMail (raw)
		self.cinfo = self.parsedEMail.getOrigin ()
		self.parm = {}
		if not self.msg.has_key (BAV.x_agn):
			if self.msg.has_key ('return-path'):
				rp = self.msg['return-path'].strip ()
				if rp[0] == '<' and rp[-1] == '>':
					addr = rp[1:-1].lower ()
					try:
						fd = open (BAV.configFile)
						for line in [l for l in fd if len (l) > 0 and l[0] != '#']:
							parts = line.split (None, 1)
							if parts[0].lower () == addr and len (parts) == 2:
								data = (parts[1]).rstrip ('\r\n')
								if data[:7] == 'accept:':
									self.msg[BAV.x_agn] = data[7:]
								break
						fd.close ()
					except IOError, e:
						agn.log (agn.LV_WARNING, 'bav', 'Cannot read file %s %s' % (BAV.configFile, `e.args`))
			else:
				agn.log (agn.LV_WARNING, 'bav', 'No %s header, neither Return-Path: found' % BAV.x_agn)
Beispiel #25
0
	def createMessage (self, orig, parm, dryrun):
		global	alock

		fname = Autoresponder.msgPattern % self.aid
		if not os.access (fname, os.R_OK):
			agn.log (agn.LV_WARNING, 'ar', 'No autoresponder mail %s for enabled autoresponder %s found' % (fname, self.aid))
			return None
		#
		if not self.allow (parm, dryrun):
			return None
		#
		try:
			fd = open (fname)
			armail = fd.read ()
			fd.close ()
			armsg = email.message_from_string (armail)
			armsg['To'] = '<%s>' % self.sender
			if not armsg.has_key ('subject') and orig.has_key ('subject'):
				subj = orig['subject']
				if len (subj) < 4 or subj[:4].lower () != 're: ':
					subj = 'Re: ' + subj
				armsg['Subject'] = subj
		except IOError, e:
			armsg = None
			agn.log (agn.LV_ERROR, 'ar', 'Unable to read %s %s' % (armail, `e.args`))
Beispiel #26
0
 def __db_sanity(self, r):
     with eagn.DB() as db:
         key = 'mask-envelope-from'
         rq = db.querys(
             'SELECT count(*) AS cnt '
             'FROM company_info_tbl '
             'WHERE company_id = 0 AND cname = :cname', {'cname': key})
         if rq is None or not rq.cnt:
             count = db.execute(
                 'INSERT INTO company_info_tbl ('
                 '       company_id, cname, cvalue, description, creation_date, timestamp'
                 ') VALUES ('
                 '       0, :cname, :cvalue, NULL, current_timestamp, current_timestamp'
                 ')', {
                     'cname': key,
                     'cvalue': 'false'
                 },
                 commit=True)
             if count == 1:
                 agn.log(agn.LV_INFO, 'sanity',
                         'Added configuration for envelope address')
             else:
                 agn.log(
                     agn.LV_ERROR, 'sanity',
                     'Failed to set configuration for envelope address: %s'
                     % db.lastError())
Beispiel #27
0
    def __init__(self, msg, mode):
        global rules, rlock

        self.msg = msg
        self.mode = mode
        self.parm = {}
        if not self.msg.has_key(BAV.x_agn):
            if self.msg.has_key('return-path'):
                rp = self.msg['return-path'].strip()
                if rp[0] == '<' and rp[-1] == '>':
                    addr = rp[1:-1].lower()
                    try:
                        fd = open(BAV.configFile)
                        for line in [
                                l for l in fd if len(l) > 0 and l[0] != '#'
                        ]:
                            parts = line.split(None, 1)
                            if parts[0].lower() == addr:
                                data = agn.chop(parts[1])
                                if data[:7] == 'accept:':
                                    self.msg[BAV.x_agn] = data[7:]
                                break
                        fd.close()
                    except IOError, e:
                        agn.log(
                            agn.LV_WARNING, 'bav', 'Cannot read file %s %s' %
                            (BAV.configFile, ` e.args `))
            else:
                agn.log(agn.LV_WARNING, 'bav',
                        'No %s header, neither Return-Path: found' % BAV.x_agn)
Beispiel #28
0
		def execute (self, size):
			global	running
			
			for path in self.ws:
				ok = True
				try:
					fd = open (path, 'r')
					body = fd.read (size)
					fd.close ()
				except IOError, e:
					agn.log (agn.LV_ERROR, 'child', 'Failed to open %s: %r' % (path, e.args))
					ok = False
				if ok:
					try:
						msg = email.message_from_string (body)
						bav = BAV (body, msg, -1)
						if bav.execute_is_no_systemmail ():
							ok = bav.execute_filter_or_forward ()
						else:
							ok = bav.execute_scan_and_unsubscribe ()
					except Exception as e:
						agn.logexc (agn.LV_ERROR, 'child', 'Fatal: catched failure: %s' % e)
						ok = False
				if ok:
					self.ws.success (bav.sender)
				else:
					self.ws.fail ()
				
				if not running:
					break
	def writeUpdateLog (self, text):
		try:
			fd = open (updateLog, 'a')
			fd.write ('%d %s\n' % (self.updateCount, text))
			fd.close ()
			self.updateCount += 1
		except IOError, e:
			agn.log (agn.LV_ERROR, 'data', 'Unable to write update log %s %s' % (updateLog, `e.args`))
	def _encode (self, s):
		if s and charset != 'UTF-8':
			temp = StringIO.StringIO (s)
			convert = codecs.EncodedFile (temp, charset, 'UTF-8')
			try:
				s = convert.read ()
			except Exception, e:
				agn.log (agn.LV_ERROR, 'auto', 'Failed to convert autoresponder text for %s %s' % (self.rid, `e.args`))
Beispiel #31
0
	def removeOldEntries (self): #{{{
		agn.log (agn.LV_INFO, 'expire', 'Remove old entries from softbounce_email_tbl')

		old = time.localtime (time.time () - 180 * 24 * 60 * 60)
		query = 'DELETE FROM softbounce_email_tbl WHERE creation_date <= :expire AND company_id'
		data = {'expire': datetime.datetime (old.tm_year, old.tm_mon, old.tm_mday)}
		self.__do (query, data, 'Remove old addresses from softbounce_email_tbl')
		agn.log (agn.LV_INFO, 'expire', 'Removing of old entries from softbounce_email_tbl done')
Beispiel #32
0
	def readMailFiles (self):
		rc = ''
		try:
			lhost = socket.getfqdn ()
			if lhost:
				rc += '@%s\taccept:rid=local\n' % lhost
		except Exception, e:
			agn.log (agn.LV_ERROR, 'data', 'Unable to find local FQDN %s' % `e.args`)
Beispiel #33
0
	def saveMessage (self, mid):
		fname = BAV.savePattern % (mid, self.rid)
		try:
			fd = open (fname, 'a')
			fd.write (self.msg.as_string (True) + '\n')
			fd.close ()
		except IOError, e:
			agn.log (agn.LV_ERROR, 'save', 'Unable to save mail copy to %s %s' % (fname, `e.args`))
Beispiel #34
0
	def __readFile (self): #{{{
		try:
			fd = open (self.path)
			content = fd.read ()
			fd.close ()
		except IOError, e:
			agn.log (agn.LV_ERROR, 'prop', 'Failed to read property file "%s": %r' % (self.path, e.args))
			content = None
Beispiel #35
0
 def append(self, line):
     try:
         self.entries.append(Entry(line))
     except re.error:
         agn.log(
             agn.LV_ERROR, 'section',
             'Got illegal regular expression "%s" in [%s]' %
             (line, self.name))
Beispiel #36
0
	def _encode (self, s):
		global	charset
		
		if s and charset != 'UTF-8':
			try:
				s = agn.toutf8 (s, charset)
			except Exception, e:
				agn.log (agn.LV_ERROR, 'auto', 'Failed to convert autoresponder text for %s %s' % (self.rid, str (e)))
Beispiel #37
0
 def completed(self, key, value, to_remove):
     if 'messageID' in value:
         messageID = value['messageID']
         if messageID:
             to_remove.append((self.SEC_MESSAGEID, messageID))
     else:
         agn.log(agn.LV_WARNING, 'proc/%s' % key,
                 'Completed record without messageID found, remove')
Beispiel #38
0
    def updateEnd(self, inst):

        agn.log(
            agn.LV_INFO, 'udpBounce',
            'Found %d hardbounces, %d softbounces, %d successes, %d ignored in %d lines'
            % (self.hbcount, self.sbcount, self.sucount, self.igcount,
               self.lineno))
        return True
Beispiel #39
0
 def __save (self, fname, line):
     rc = False
     try:
         fd = open (fname, 'a')
         fd.write (line + '\n')
         fd.close ()
         rc = True
     except IOError, e:
         agn.log (agn.LV_ERROR, 'update', 'Failed to write to %s: %s' % (fname, `e.args`))
Beispiel #40
0
 def update (self, inst):
     tfname = self.renameToTemp ()
     if tfname is None:
         return False
     try:
         fd = open (tfname, 'r')
     except IOError, e:
         agn.log (agn.LV_ERROR, 'update', 'Unable to open %s: %s' % (tfname, `e.args`))
         fd = None
Beispiel #41
0
	def sendmail (self, msg, to):
		try:
			mailtext = msg.as_string (False)

			pp = os.popen ('/usr/sbin/sendmail ' + to, 'w')
			pp.write (mailtext)
			pp.close ()
		except Exception, e:
			agn.log (agn.LV_ERROR, 'sendmail', 'Sending mail to %s failed %s' % (to, `e.args`))
Beispiel #42
0
	def __scan (self, msg, scan, sects, checkheader):
		if checkheader:
			if not scan.section:
				rc = self.__checkHeader (msg, sects)
				if rc:
					(scan.section, scan.entry, scan.reason) = rc
			self.__scanMID (scan, msg['message-id'], 'header')
		if not scan.dsn:
			subj = msg['subject']
			if subj:
				mt = Rule.DSNRE[0].search (self.__decode (subj))
				if mt:
					grps = mt.groups ()
					scan.dsn = grps[0]
					scan.etext = grps[1]
					agn.log (agn.LV_VERBOSE, 'dsn', 'Found DSN in Subject: %s' % subj)
			if not scan.dsn:
				action = msg['action']
				status = msg['status']
				if action and status:
					mt = Rule.DSNRE[2].match (self.__decode (status))
					if mt:
						scan.dsn = mt.groups ()[0]
						scan.etext = 'Action: ' + action
						agn.log (agn.LV_VERBOSE, 'dsn', 'Found DSN in Action: %s / Status: %s' % (action, status))
		pl = msg.get_payload (decode = True)
		if not pl:
			pl = msg.get_payload ()
		if type (pl) in types.StringTypes:
			for line in pl.split ('\n'):
				if not scan.minfo:
					self.__scanMID (scan, line, 'body')
				if not scan.section:
					(sec, ent) = self.__match (line, sects)
					if sec:
						scan.section = sec
						scan.entry = ent
						scan.reason = line
						agn.log (agn.LV_VERBOSE, 'match', 'Found pattern "%s" in body "%s"' % (scan.entry.pattern, line))
				if not scan.dsn:
					mt = Rule.DSNRE[0].search (line)
					if mt:
						grps = mt.groups ()
						scan.dsn = grps[0]
						scan.etext = grps[1]
						agn.log (agn.LV_VERBOSE, 'dsn', 'Found DSN %s / Text "%s" in body: %s' % (scan.dsn, scan.etext, line))
					else:
						mt = Rule.DSNRE[1].search (line)
						if mt:
							scan.dsn = mt.groups ()[0]
							scan.etext = line
							agn.log (agn.LV_VERBOSE, 'dsn', 'Found DSN %s in body: %s' % (scan.dsn, line))
		elif type (pl) in [ types.TupleType, types.ListType ]:
			for p in pl:
				self.__scan (p, scan, sects, True)
				if scan.section and scan.dsn and scan.minfo:
					break
Beispiel #43
0
 def __readFile(self):  #{{{
     try:
         fd = open(self.path)
         content = fd.read()
         fd.close()
     except IOError, e:
         agn.log(
             agn.LV_ERROR, 'prop',
             'Failed to read property file "%s": %r' % (self.path, e.args))
         content = None
Beispiel #44
0
	def unlock (self, key):
		try:
			self.locks[key] -= 1
			if self.locks[key] <= 0:
				del self.locks[key]
				agn.log (agn.LV_DEBUG, 'lock', '%r removed' % key)
			else:
				agn.log (agn.LV_DEBUG, 'lock', '%r decreased' % key)
		except KeyError:
			pass
Beispiel #45
0
	def execute_scan_and_unsubscribe (self):
		scan = self.rule.scanMessage (self.msg, ['hard', 'soft'])
		if scan and scan.section and scan.minfo:
			try:
				fd = open (BAV.extBouncelog, 'a')

				fd.write ('%s;0;%d;0;%d;mailloop=%s\n' % (scan.dsn, scan.minfo[0], scan.minfo[1], scan.etext))
				fd.close ()
			except IOError, e:
				agn.log (agn.LV_ERROR, 'log', 'Unable to write %s %s' % (BAV.extBouncelog, `e.args`))
	def readMailFiles (self):
		rc = ''

		if self.sendmailFree:
			return rc
		try:
			for line in fileReader (mailBase + '/local-host-names'):
				rc += '@%s\taccept:rid=local\n' % line
		except IOError, e:
			agn.log (agn.LV_ERROR, 'data', 'Unable to read local-host-names %s' % `e.args`)
Beispiel #47
0
 def updateLine (self, inst, line):
     parts = line.split (';', 5)
     if len (parts) != 6:
         agn.log (agn.LV_WARNING, 'updBounce', 'Got invalid line: ' + line)
         return False
     try:
         (dsn, _, mailing, media, customer, info) = (parts[0], int (parts[1]), int (parts[2]), int (parts[3]), int (parts[4]), parts[5])
     except ValueError, e:
         agn.log (agn.LV_WARNING, 'updBounce', 'Unable to parse line: ' + line + ' (' + str (e) + ')')
         return False
Beispiel #48
0
 def renameToTemp (self):
     tfname = self.path + '.%d.%d.%d' % (self.pid, time.time (), self.cur)
     self.cur += 1
     try:
         os.rename (self.path, tfname)
         agn.log (agn.LV_INFO, 'update', 'Renamed %s to %s' % (self.path, tfname))
         time.sleep (10)
     except OSError, e:
         agn.log (agn.LV_ERROR, 'update', 'Unable to rename %s to %s: %s' % (self.path, tfname, `e.args`))
         tfname = None
	def readLocalFiles (self):
		rc = ''

		if agn.iswin:
			return rc
		try:
			for line in fileReader (localFilename):
				rc += line + '\n'
		except IOError, e:
			agn.log (agn.LV_VERBOSE, 'local', 'Unable to read local file %s %s' % (localFilename, `e.args`))
Beispiel #50
0
	def checkProcmailrc (now, destpath):
		prc = agn.mkpath (agn.base, '.procmailrc')
		try:
			fd = open (prc, 'r')
			ocontent = fd.read ()
			fd.close ()
		except IOError, e:
			if e.args[0] != errno.ENOENT:
				agn.log (agn.LV_WARNING, 'chk', 'Failed to read "%s": %r' % (prc, e.args))
			ocontent = ''
Beispiel #51
0
	def waitForChildren (children):
		nchildren = []
		for child in children:
			child.wait ()
			if child.active:
				nchildren.append (child)
		if len (children) != len (nchildren):
			count = len (children) - len (nchildren)
			agn.log (agn.LV_VERBOSE, 'bavd', '%d child%s terminated' % (count, count != 1 and 'ren' or ''))
		return nchildren
Beispiel #52
0
    def __todetail(self, dsn, info):
        (ignore, detail, code, typ, remark) = (False, 0, 0, 2, 'bounce')
        match = self.dsnparse.match(dsn)
        if not match is None:
            grp = match.groups()
            code = int(grp[0]) * 100 + int(grp[1]) * 10 + int(grp[2])
            infos = UpdateInfo(info)
            stat = infos.get('stat', '').lower()
            mailloop = infos['mailloop']

            #
            # special cases
            if infos.get('relay', '').find('yahoo.com') != -1:
                if code / 100 == 5 and stat.find('service unavailable') != -1:
                    detail = 511
            admin = infos['admin']
            if not admin is None:
                typ = 4
                remark = admin
            status = infos['status']
            if not status is None:
                ttyp = self.ustatus.findStatus(status)
                if not ttyp is None:
                    typ = ttyp

            if detail == 0:
                if (code in (511, 571) and
                    (stat.find('user unknown') != -1
                     or not mailloop is None)) or code == 513:
                    detail = 511
                elif code == 512:
                    detail = 512
                elif code in (420, 421, 422, 521, 522):
                    detail = 420
                elif code in (430, 530, 535):
                    detail = 430
                elif code / 100 == 4:
                    if code / 10 in (42, 43,
                                     47) and (stat.find('gray') != -1
                                              or stat.find('grey') != -1):
                        ignore = True
                    detail = 400
                elif code in (500, 511, 550, 554):
                    detail = 500
                elif code / 100 == 5:
                    detail = 510
                elif code == 200:
                    detail = 200
                    typ = 1
                else:
                    agn.log(
                        agn.LV_WARNING, 'updBounce',
                        '%s resulting in %d does not match any rule' %
                        (dsn, code))
        return (ignore, detail, code, typ, remark)
Beispiel #53
0
	def __mapMailingToCompany (self, inst, mailing):
		if not self.mailingMap.has_key (mailing):
			rec = inst.querys ('SELECT company_id FROM mailing_tbl WHERE mailing_id = %d' % mailing)
			if rec is None:
				agn.log (agn.LV_ERROR, 'updBounce', 'No company_id for mailing %d found' % mailing)
				return 0
			else:
				self.mailingMap[mailing] = rec[0]
				return rec[0]
		else:
			return self.mailingMap[mailing]
Beispiel #54
0
			def save (ct):
				if ct.path is not None and (ct.modified or not os.path.isfile (ct.path)):
					try:
						fd = open (ct.path, 'w')
						if ct.content:
							fd.write ('\n'.join (['%s\t%s' % _c for _c in ct.content]) + '\n')
						fd.close ()
						agn.log (agn.LV_INFO, 'data', 'Written %d lines to %s' % (len (ct.content), ct.path))
						if ct.hash is not None:
							make (ct)
					except OSError, e:
						agn.log (agn.LV_ERROR, 'data', 'Failed to save %s: %s' % (ct.path, str (e)))
	def updateConfigfile (self, new):
		if new != self.last:
			temp = configFilename + '.%d' % os.getpid ()
			try:
				fd = open (temp, 'w')
				fd.write (new)
				fd.close ()
				self.renameFile (temp, configFilename)
				self.last = new
			except IOError, e:
				agn.log (agn.LV_ERROR, 'data', 'Unable to write %s %s' % (temp, `e.args`))
				raise agn.error ('updateConfigfile.open')
	def update (self, forced):
		try:
			auto = []
			new = self.readMailFiles ()
			new += self.readDatabase (auto)
			new += self.readLocalFiles ()
			self.updateAutoresponder (auto)
			self.updateConfigfile (new)
			updateText = 'success'
		except agn.error, e:
			agn.log (agn.LV_ERROR, 'data', 'Update failed: ' + e.msg)
			updateText = 'failed: ' + e.msg
	def __collect (self, path, remove): #{{{
		files = os.listdir (path)
		for fname in [_f for _f in files if not self.pattern.match (_f) is None]:
			fpath = agn.mkpath (path, fname)
			if remove:
				try:
					os.unlink (fpath)
					agn.log (agn.LV_DEBUG, 'collect', 'File "%s" removed' % fpath)
				except OSError, e:
					agn.log (agn.LV_ERROR, 'collect', 'Failed to remove file "%s": %r' % (fpath, e.args))
			elif fname.endswith ('.xml.gz'):
				self.__parseXML (fpath)
	def __todetail (self, dsn, info):
		(ignore, detail, code, typ, remark) = (False, 0, 0, 2, 'bounce')
		match = self.dsnparse.match (dsn)
		if not match is None:
			grp = match.groups ()
			code = int (grp[0]) * 100 + int (grp[1]) * 10 + int (grp[2])
			infos = UpdateInfo (info)
			stat = infos.get ('stat', '').lower ()
			mailloop = infos['mailloop']
			
			#
			# special cases
			relay = infos.get ('relay', None)
			if relay is not None:
				if relay.find ('yahoo.com') != -1:
					if code / 100 == 5 and stat.find ('service unavailable') != -1:
						detail = 511
			admin = infos['admin']
			if not admin is None:
				typ = 4
				remark = admin
			status = infos['status']
			if not status is None:
				ttyp = self.ustatus.findStatus (status)
				if not ttyp is None:
					typ = ttyp

			if detail == 0:
				if (code in (511, 571) and (stat.find ('user unknown') != -1 or not mailloop is None)) or code == 513:
					detail = 511
				elif code == 512:
					detail = 512
				elif code in (420, 421, 422, 521, 522):
					detail = 420
				elif code in (430, 530, 535):
					detail = 430
				elif code / 100 == 4:
					if code / 10 in (42, 43, 47) and (stat.find ('gray') != -1 or stat.find ('grey') != -1):
						ignore = True
					detail = 400
				elif code in (500, 511, 550, 554):
					detail = 500
				elif code / 100 == 5:
					detail = 510
				elif code == 200:
					detail = 200
					typ = 1
				elif code / 100 == 1:
					detail = 100
					typ = 1
				else:
					agn.log (agn.LV_WARNING, 'updBounce', '%s resulting in %d does not match any rule' % (dsn, code))
		return (ignore, detail, code, typ, remark)
Beispiel #59
0
	def updateLine (self, inst, line):
		sql = 'INSERT INTO mailing_account_tbl ('
		values = 'VALUES ('

		timestamp = 'now()'
		sep = ''
		ignore = False
		for tok in line.split ():
			tup = tok.split ('=', 1)
			if len (tup) == 2:
				name = None
				(var, val) = tup
				quoteit = False

				if var == 'company':
					name = 'company_id'
				elif var == 'mailing':
					name = 'mailing_id'
				elif var == 'maildrop':
					name = 'maildrop_id'
				elif var == 'status_field':
					name = 'status_field'
					quoteit = True
				elif var in ('mailtype', 'subtype'):
					name = 'mailtype'
				elif var == 'count':
					name = 'no_of_mailings'
				elif var == 'bytes':
					name = 'no_of_bytes'
				elif var == 'block':
					name = 'blocknr'
				elif var == 'timestamp':
					if not self.tscheck.match (val) is None:

						timestamp = 'str_to_date(\'' + val + '\', \'%Y-%m-%d:%H:%i:%s\')'
				if quoteit:
					val = '\'%s\'' % val.replace ('\'', '\'\'')
				if not name is None:
					sql += '%s%s' % (sep, name)
					values += '%s%s' % (sep, val)
					sep = ', '

		sql += '%schange_date) %s, %s)' % (sep, values, timestamp)
		rc = True
		if not ignore:
			try:
				inst.update (sql, commit = True)
				self.inserted += 1
			except agn.error, e:
				agn.log (agn.LV_ERROR, 'updAccount', 'Failed to insert %s into database: %s' % (line, e.msg))
				rc = False
				self.failed += 1
Beispiel #60
0
	def _encode (self, s):
		if s:
			try:
				s = unicode (s, charset).encode ('UTF-8')
			except Exception, e:
				agn.log (agn.LV_ERROR, 'auto', 'Failed to convert autoresponder text for %s: %s' % (self.rid, str (e)))
				ns = []
				for ch in s:
					if ord (ch) < 128:
						ns.append (ch)
					else:
						ns.append ('?')
				s = ''.join (ns)