- remove domain specific code from mail tools
- make mail aliases and pop3 accounts domain properties - add class for system users - move GNVDomain class to gnuviech package - add more logging - add password hashing, passwd and shadow functions to gnuviech.tools git-svn-id: file:///home/www/usr01/svn/gnuviechadmin/gnuviech.info/gnuviechadmin/trunk@87 a67ec6bc-e5d5-0310-a910-815c51eb3124
This commit is contained in:
parent
b9ec217d1e
commit
fa6961463e
6 changed files with 316 additions and 76 deletions
|
@ -8,7 +8,7 @@ from log4py import Logger, FileAppender, LOGLEVEL_DEBUG
|
|||
|
||||
class GNVPrefs:
|
||||
"""This class has static variables for the settings of the GNUViech
|
||||
administration tool. These settings can be customized in the file
|
||||
administration tool. These settings may be customized in the file
|
||||
gvadm.preferences."""
|
||||
# define standard values
|
||||
PWDMINLENGTH = 6
|
||||
|
@ -31,10 +31,33 @@ class GNVPrefs:
|
|||
WEBSTATSDIR = WEBHOMEDIR+"stats/"
|
||||
LOGDIR = BASEPREFIX+"/var/log"
|
||||
LOGFILE = LOGDIR+"/gnvadm.log"
|
||||
USERTYPES = {
|
||||
"web" : {
|
||||
"minuid" : 10000,
|
||||
"maxuid" : 10999,
|
||||
"group" : "wwwusers",
|
||||
"fullname" : "Webuser %s",
|
||||
"home" : WEBHOMEDIR + "%s",
|
||||
"shell" : "/bin/true",
|
||||
"nohome" : 1,
|
||||
"disabledpass" : 1
|
||||
},
|
||||
"pop3" : {
|
||||
"minuid" : 20000,
|
||||
"maxuid" : 29999,
|
||||
"group" : "poponly",
|
||||
"fullname" : "Popuser %s",
|
||||
"home" : POPHOMEDIR + "%s",
|
||||
"shell" : "/bin/true",
|
||||
"nohome" : 1,
|
||||
"disabledpass" : 1
|
||||
}
|
||||
}
|
||||
# load custom settings
|
||||
execfile("gvadm.preferences")
|
||||
|
||||
def __init__(self):
|
||||
self.logger = self.getLogger(self)
|
||||
self.setupDirs()
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -76,6 +99,30 @@ class GNVPrefs:
|
|||
logger.set_loglevel(LOGLEVEL_DEBUG)
|
||||
return logger
|
||||
|
||||
def getNextSysId(self, type):
|
||||
nextid = self.USERTYPES[type]["minuid"]
|
||||
file = open(self.BASEPREFIX+"/etc/passwd", "r")
|
||||
for line in file.readlines():
|
||||
pwdline = tools.splitPasswdLine(line)
|
||||
self.logger.debug(str(pwdline))
|
||||
uid = int(pwdline["uid"])
|
||||
if (uid in
|
||||
range(int(self.USERTYPES[type]["minuid"]),
|
||||
int(self.USERTYPES[type]["maxuid"]))
|
||||
and nextid <= uid): nextid = uid+1
|
||||
return nextid
|
||||
|
||||
def getGroupId(self, type): pass
|
||||
|
||||
def getFullName(self, type, username):
|
||||
return self.USERTYPES[type]["fullname"] % username
|
||||
|
||||
def getHomeDir(self, type, username):
|
||||
return self.USERTYPES[type]["home"] % username
|
||||
|
||||
def getShell(self, type):
|
||||
return self.USERTYPES[type]["shell"]
|
||||
|
||||
class NoAdmDirError(Exception):
|
||||
"""This exception is raised if the admin directory does'nt exist."""
|
||||
pass
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
Germany
|
||||
"""
|
||||
|
||||
import os
|
||||
import os, pwd
|
||||
import gnuviech
|
||||
from gnuviech import sysuser
|
||||
|
||||
class DomainNotExistentError(Exception): pass
|
||||
|
||||
|
@ -14,19 +15,27 @@ class DomainFileNotExistentError(Exception): pass
|
|||
class GNVDomain:
|
||||
"""Represents a domain in the GNUViech admin tool"""
|
||||
|
||||
def __init__(self, domain):
|
||||
def __init__(self, domain, prefs):
|
||||
"""Initializes the domain object"""
|
||||
self.logger = prefs.getLogger(self)
|
||||
self.prefs = prefs
|
||||
self.name = domain
|
||||
self.webaccount = None
|
||||
self.zone = None
|
||||
self.statsusers = {}
|
||||
self.mailaliases = {}
|
||||
self.pop3accounts = {}
|
||||
try:
|
||||
self.findUser()
|
||||
self.__findUser()
|
||||
except gnuviech.NoAdmDirError:
|
||||
gnuviech.setupDirs()
|
||||
prefs.setupDirs()
|
||||
self.__init__(domain)
|
||||
except DomainFileNotExistentError:
|
||||
self.createDomainFile()
|
||||
self.__init__(domain)
|
||||
self.__createDomainFile()
|
||||
self.__init__(domain, prefs)
|
||||
except DomainNotExistentError:
|
||||
self.createUser()
|
||||
self.__createUser()
|
||||
self.createWebUser()
|
||||
|
||||
def __repr__(self):
|
||||
retval = "Domain "+self.name
|
||||
|
@ -36,36 +45,36 @@ class GNVDomain:
|
|||
retval += ", new domain"
|
||||
return retval
|
||||
|
||||
def createDomainFile(self):
|
||||
def __createDomainFile(self):
|
||||
"""Create the domain user id map file."""
|
||||
file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "w")
|
||||
file.close()
|
||||
|
||||
def createUser(self):
|
||||
def __createUser(self):
|
||||
"""Create a user for the domain."""
|
||||
file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "r")
|
||||
file = open(self.prefs.GVADMDIR+"domains", "r")
|
||||
id = 0
|
||||
for line in file.readlines():
|
||||
(key, value) = line.split(":")
|
||||
if (int(value) > id): id = int(value)
|
||||
file.close()
|
||||
id += 1
|
||||
file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "a")
|
||||
file = open(self.prefs.GVADMDIR+"domains", "a")
|
||||
file.write("%s:%d\n" % (self.name, id))
|
||||
file.close()
|
||||
self.findUser()
|
||||
self.__findUser()
|
||||
|
||||
def findUser(self):
|
||||
def __findUser(self):
|
||||
"""Finds the user for the domain."""
|
||||
self.username = None
|
||||
if (os.access(gnuviech.GNVPrefs.GVADMDIR, os.R_OK)):
|
||||
if (os.access(self.prefs.GVADMDIR, os.R_OK)):
|
||||
try:
|
||||
domainsfile = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "r")
|
||||
domainsfile = open(self.prefs.GVADMDIR+"domains", "r")
|
||||
for line in domainsfile.readlines():
|
||||
(key, value) = line.split(":")
|
||||
if (key == self.name):
|
||||
self.username = "%s%02d" % (
|
||||
gnuviech.GNVPrefs.USERPREFIX,
|
||||
self.prefs.USERPREFIX,
|
||||
int(value))
|
||||
domainsfile.close()
|
||||
if self.username is None:
|
||||
|
@ -96,6 +105,48 @@ class GNVDomain:
|
|||
if (usertype == "pop3"):
|
||||
return "%sp%d" % (self.username, self.getMaxPop3Id()+1)
|
||||
|
||||
def addPOP3Account(self, account):
|
||||
self.pop3accounts[account.localpart] = account
|
||||
|
||||
def addMailAlias(self, alias):
|
||||
self.mailaliases[alias.localpart] = alias
|
||||
|
||||
def createWebUser(self):
|
||||
try:
|
||||
self.webaccount = sysuser.SystemUser(self.prefs, self.username)
|
||||
except sysuser.UserNotInPasswdError:
|
||||
self.webaccount = sysuser.createUser(self.prefs, self.username,
|
||||
"web")
|
||||
self.logger.debug(str(self.webaccount))
|
||||
|
||||
# #!/bin/sh
|
||||
# . /usr/local/etc/preferences
|
||||
# if [ -n $USERPREFIX ]; then
|
||||
# USERPREFIX="usr"
|
||||
# fi
|
||||
# if [ $1 == "" ]; then
|
||||
# echo "usage: $0 <usernum>"
|
||||
# exit
|
||||
# fi
|
||||
|
||||
# NEWUSER="$USERPREFIX$1"
|
||||
# NEWHOME="/home/www/$NEWUSER"
|
||||
# LOGDIR="/home/www/logfiles/$NEWUSER"
|
||||
|
||||
# adduser --home "$NEWHOME" --shell /bin/true --no-create-home --firstuid 10000 --ingroup wwwusers --disabled-password --gecos "Webuser $NEWUSER" $NEWUSER
|
||||
|
||||
# echo "${NEWUSER}:${NEWPASS}" | chpasswd
|
||||
# mkdir -p "$NEWHOME/"{html,cgi-bin}
|
||||
# mkdir -p "$LOGDIR"
|
||||
# chown -Rc www-data.www-data "$LOGDIR"
|
||||
# chmod 0750 "$LOGDIR"
|
||||
# chown -Rc $NEWUSER.wwwusers "$NEWHOME"
|
||||
# mkdir -p "$NEWHOME/html/stats"
|
||||
# chown modlogan.wwwusers "$NEWHOME/html/stats"
|
||||
# htpasswd -bc "/home/www/${NEWUSER}stats" "${NEWUSER}" "${NEWPASS}"
|
||||
|
||||
# echo added new web user $NEWUSER with password $NEWPASS
|
||||
|
||||
if __name__ == "__main__":
|
||||
dom = GNVDomain("dittberner.info")
|
||||
print dom
|
62
backend/gnuviech/sysuser.py
Normal file
62
backend/gnuviech/sysuser.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
from gnuviech import tools
|
||||
|
||||
class UserNotInPasswdError(Exception): pass
|
||||
|
||||
class NoPasswordInShadowError(Exception): pass
|
||||
|
||||
class SystemUser:
|
||||
def __init__(self, prefs, username):
|
||||
self.prefs = prefs
|
||||
self.logger = prefs.getLogger(self)
|
||||
self.getUser(username)
|
||||
self.logger.debug(str(self))
|
||||
|
||||
def getUser(self, username):
|
||||
pwdfile = open(self.prefs.BASEPREFIX+"/etc/passwd", "r")
|
||||
for line in pwdfile.readlines():
|
||||
pwdline = tools.splitPasswdLine(line)
|
||||
self.logger.debug("PWDLINE: %s" % pwdline)
|
||||
if pwdline["loginname"] == username:
|
||||
self.username = pwdline["loginname"]
|
||||
self.password = self.getPassword()
|
||||
self.uid = pwdline["uid"]
|
||||
self.gid = pwdline["gid"]
|
||||
self.fullname = pwdline["fullname"]
|
||||
self.homedir = pwdline["homedir"]
|
||||
self.shell = pwdline["shell"]
|
||||
return
|
||||
pwdfile.close()
|
||||
raise UserNotInPasswdError
|
||||
|
||||
def getPassword(self):
|
||||
shadowfile = open(self.prefs.BASEPREFIX+"/etc/shadow", "r")
|
||||
for line in shadowfile.readlines():
|
||||
shadowline = tools.splitShadowLine(line)
|
||||
self.logger.debug("SHADOWLINE: %s" % shadowline)
|
||||
if shadowline["loginname"] == self.username:
|
||||
shadowfile.close()
|
||||
return shadowline["passwordhash"]
|
||||
shadowfile.close()
|
||||
raise NoPasswordInShadowError
|
||||
|
||||
def createUser(prefs, username, type):
|
||||
line = ":".join((username, "x",
|
||||
str(prefs.getNextSysId(type)),
|
||||
str(prefs.getGroupId(type)),
|
||||
prefs.getFullName(type, username),
|
||||
prefs.getHomeDir(type, username),
|
||||
prefs.getShell(type)))
|
||||
passwdfile = open(prefs.BASEPREFIX+"/etc/passwd", "a")
|
||||
passwdfile.write("%s\n" % line)
|
||||
passwdfile.close()
|
||||
createShadowItem(prefs, username, type, tools.generatePassword())
|
||||
return SystemUser(prefs, username)
|
||||
|
||||
def createShadowItem(prefs, username, type, password):
|
||||
line = ":".join((username,
|
||||
tools.hashPassword(password, "md5"),
|
||||
str(tools.daysSince1970()),
|
||||
"0", "99999", "7", "", "", ""))
|
||||
shadowfile = open(prefs.BASEPREFIX+"/etc/shadow", "a")
|
||||
shadowfile.write("%s\n" % line)
|
||||
shadowfile.close()
|
|
@ -5,16 +5,62 @@
|
|||
|
||||
import random, re
|
||||
from gnuviech import GNVPrefs
|
||||
from crypt import crypt
|
||||
from time import time
|
||||
|
||||
def generatePassword():
|
||||
"""Generates a password from the chars in GNVPrefs.PWDCHARS with
|
||||
a length between GNVPrefs.PWDMINLENGTH and GNVPrefs.PWDMAXLENGTH."""
|
||||
return "".join([chr(char) for char in
|
||||
random.sample(GNVPrefs.PWDCHARS,
|
||||
random.randint(GNVPrefs.PWDMINLENGTH,
|
||||
GNVPrefs.PWDMAXLENGTH))])
|
||||
|
||||
def generateSalt():
|
||||
saltchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
salt = []
|
||||
for i in range(8):
|
||||
salt.append(saltchars[random.randint(0, len(saltchars) - 1)])
|
||||
return "".join(salt)
|
||||
|
||||
def checkEmail(email):
|
||||
"""Returns a match object if the given email address is syntactically
|
||||
correct otherwise it returns None"""
|
||||
# regex for email check
|
||||
p = re.compile(r'^([a-zA-Z0-9_\-.]+)@([a-zA-Z0-9\-]+(\.|[a-zA-Z0-9\-]+)*\.[a-z]{2,5})$')
|
||||
return p.search(email)
|
||||
|
||||
def splitPasswdLine(line):
|
||||
loginname, password, uid, gid, fullname, directory, shell = line.split(":")
|
||||
return {
|
||||
"loginname" : loginname,
|
||||
"password" : password,
|
||||
"uid" : uid,
|
||||
"gid" : gid,
|
||||
"fullname" : fullname,
|
||||
"homedir" : directory,
|
||||
"shell" : shell
|
||||
}
|
||||
|
||||
def splitShadowLine(line):
|
||||
(loginname, passwordhash, lastchange, maychange, mustchange, warnexpire,
|
||||
disabled, disabledsince, reserved) = line.split(":")
|
||||
return {
|
||||
"loginname" : loginname,
|
||||
"passwordhash" : passwordhash,
|
||||
"lastchange" : lastchange,
|
||||
"maychange" : maychange,
|
||||
"mustchange" : mustchange,
|
||||
"warnexpire" : warnexpire,
|
||||
"disabled" : disabled,
|
||||
"disabledsince" : disabledsince,
|
||||
"reserved" : reserved
|
||||
}
|
||||
|
||||
def hashPassword(password, method="md5"):
|
||||
if (method == "md5"):
|
||||
return crypt(password, "$1$%s" % generateSalt())
|
||||
return crypt(password, generateSalt())
|
||||
|
||||
def daysSince1970():
|
||||
return int(time()/(3600*24))
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
import os, string
|
||||
import gnuviech
|
||||
from GNVAdm import GNVDomain
|
||||
#from GNVAdm import GNVDomain
|
||||
from gnuviech import GNVPrefs, tools
|
||||
from gnuviech.gnvdomain import GNVDomain
|
||||
|
||||
# if [ -n $USERPREFIX ]; then
|
||||
# USERPREFIX="usr"
|
||||
|
@ -27,81 +29,107 @@ from GNVAdm import GNVDomain
|
|||
# echo "Herzlich willkommen auf dem GNU-Viech" | mail -s "Willkommen auf dem GNU-Viech" ${NEWUSER}
|
||||
# echo added new pop3 user $NEWUSER with password $NEWPASS
|
||||
|
||||
class MailAliasExists(Exception): pass
|
||||
|
||||
class POP3AccountExists(Exception): pass
|
||||
|
||||
class MailAccount:
|
||||
def __init__(self, domain):
|
||||
def __init__(self, domain, localpart):
|
||||
"Initialize a MailAccount instance for a given domain"
|
||||
if (not os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK & os.X_OK)):
|
||||
self.setupDirs()
|
||||
self.domain = domain
|
||||
self.localpart = localpart
|
||||
self.prefs = domain.prefs
|
||||
self.logger = domain.prefs.getLogger(self)
|
||||
|
||||
def setupDirs(self):
|
||||
os.mkdir(gnuviech.GNVPrefs.VIRTUALDOMDIR)
|
||||
def __repr__(self):
|
||||
return "%s@%s" % (self.localpart, self.domain.name)
|
||||
|
||||
class MailAlias(MailAccount):
|
||||
"""This represents a mail alias"""
|
||||
|
||||
def __init__(self, domain):
|
||||
def __init__(self, domain, localpart, target):
|
||||
"Initialize the POPAccount class for a given domain"
|
||||
MailAccount.__init__(self, domain)
|
||||
self.aliases = {}
|
||||
self.readAll()
|
||||
if localpart in domain.mailaliases.keys():
|
||||
raise MailAliasExists
|
||||
MailAccount.__init__(self, domain, localpart)
|
||||
self.setTarget(target)
|
||||
|
||||
def setTarget(self, target):
|
||||
self.target = target
|
||||
self.logger.debug("setting target for alias %s to %s." %
|
||||
(str(self), self.target))
|
||||
# self.aliases = {}
|
||||
# self.readAll()
|
||||
|
||||
def readAll(self):
|
||||
"""reads the aliasfile for the given domain"""
|
||||
self.aliases = {}
|
||||
if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK)):
|
||||
try:
|
||||
aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name , 'r')
|
||||
for line in aliasfile.readlines():
|
||||
keyvals = string.split(line,":",1)
|
||||
self.aliases[keyvals[0]] = keyvals[1].strip()
|
||||
aliasfile.close()
|
||||
except IOError:
|
||||
print "couldn't read the aliasfile for "+self.domain.name+"."
|
||||
else:
|
||||
print "couldn't read from "+gnuviech.GNVPrefs.VIRTUALDOMDIR+"."
|
||||
# def readAll():
|
||||
# """reads the aliasfile for the given domain"""
|
||||
# self.aliases = {}
|
||||
# if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK)):
|
||||
# try:
|
||||
# aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name , 'r')
|
||||
# for line in aliasfile.readlines():
|
||||
# keyvals = string.split(line,":",1)
|
||||
# self.aliases[keyvals[0]] = keyvals[1].strip()
|
||||
# aliasfile.close()
|
||||
# except IOError:
|
||||
# self.logger.error("couldn't read the aliasfile for "+self.domain.name+".")
|
||||
# else:
|
||||
# self.logger.error("couldn't read from "+gnuviech.GNVPrefs.VIRTUALDOMDIR+".")
|
||||
|
||||
def writeAll(self):
|
||||
"""writes the aliasfile for the given domain with the aliases defined
|
||||
in the dictionary object aliases"""
|
||||
if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.W_OK)):
|
||||
try:
|
||||
aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name, 'w')
|
||||
keys = self.aliases.keys();
|
||||
keys.sort();
|
||||
for key in keys:
|
||||
aliasfile.write("%s:%s" % (key, self.aliases[key]) + "\n")
|
||||
aliasfile.close()
|
||||
except IOError:
|
||||
print "writing to aliasfile failed."
|
||||
else:
|
||||
print "no write access to directory "+gnuviech.GNVPrefs.VIRTUALDOMDIR+"."
|
||||
# def writeAll(self):
|
||||
# """writes the aliasfile for the given domain with the aliases defined
|
||||
# in the dictionary object aliases"""
|
||||
# if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.W_OK)):
|
||||
# try:
|
||||
# aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name, 'w')
|
||||
# keys = self.aliases.keys();
|
||||
# keys.sort();
|
||||
# for key in keys:
|
||||
# aliasfile.write("%s:%s" % (key, self.aliases[key]) + "\n")
|
||||
# aliasfile.close()
|
||||
# except IOError:
|
||||
# self.logger.error("writing to aliasfile failed.")
|
||||
# else:
|
||||
# self.logger.error("no write access to directory "+gnuviech.GNVPrefs.VIRTUALDOMDIR+".")
|
||||
|
||||
def setAlias(self, alias, target):
|
||||
"""sets a mail alias for given domain which directs the MTA to the
|
||||
given target
|
||||
"""
|
||||
self.readAll()
|
||||
self.aliases[alias]=target
|
||||
self.writeAll()
|
||||
# def setAlias(self, alias, target):
|
||||
# """sets a mail alias for given domain which directs the MTA to the
|
||||
# given target
|
||||
# """
|
||||
# self.readAll()
|
||||
# self.aliases[alias]=target
|
||||
# self.writeAll()
|
||||
|
||||
class POP3Account(MailAccount):
|
||||
"""This represents a pop 3 account"""
|
||||
|
||||
def create(self, address):
|
||||
"""Creates a pop3/imap account for the domain"""
|
||||
print self
|
||||
print "adding address "+address
|
||||
alias = MailAlias(self.domain)
|
||||
alias.setAlias(address, self.domain.getNextUser("pop3"))
|
||||
print alias
|
||||
def __init__(self, domain, localpart):
|
||||
"""Creates a new pop3 mail account"""
|
||||
if localpart in domain.pop3accounts.keys():
|
||||
raise POP3AccountExists
|
||||
MailAccount.__init__(self, domain, localpart)
|
||||
self.logger.debug("adding address %s@%s." % (self.localpart,
|
||||
self.domain.name))
|
||||
self.setPassword(tools.generatePassword())
|
||||
self.setSysUser(domain.getNextUser("pop3"))
|
||||
self.domain.addMailAlias(MailAlias(self.domain,
|
||||
self.localpart, self.sysuser))
|
||||
|
||||
def setPassword(self, newpassword):
|
||||
self.password = newpassword
|
||||
self.logger.debug("set password for %s to %s." %
|
||||
(str(self), self.password))
|
||||
|
||||
def setSysUser(self, username):
|
||||
self.sysuser = username
|
||||
self.logger.debug("set system user for %s to %s" %
|
||||
(str(self), self.sysuser))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
popacc = POP3Account(GNVDomain("dittberner.info"))
|
||||
print popacc
|
||||
popacc.create("test")
|
||||
|
||||
alias = MailAlias(GNVDomain("dittberner.info"))
|
||||
print alias
|
||||
alias.setAlias("klaus", "klaus@dittberner.info")
|
||||
print alias
|
||||
prefs = GNVPrefs()
|
||||
domain = GNVDomain("dittberner.info", prefs)
|
||||
domain.addPOP3Account(POP3Account(domain, "test"))
|
||||
domain.addMailAlias(MailAlias(domain, "klaus", "klaus@test.de"))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import gnuviech, sys
|
||||
import gnuviech.tools
|
||||
from gnuviech.gnvdomain import GNVDomain
|
||||
|
||||
class Test:
|
||||
def __init__(self, prefs):
|
||||
|
@ -29,6 +30,11 @@ maximum password length: %d""" % (avglen, minlen, maxlen))
|
|||
self.logger.debug("%s is a valid email address." % address)
|
||||
else:
|
||||
self.logger.debug("%s is an invalid email address." % address)
|
||||
|
||||
domain = GNVDomain("dittberner.info", self.prefs)
|
||||
self.logger.debug("Domain %s." % domain)
|
||||
domain = GNVDomain("jesusgemeindesohland.de", self.prefs)
|
||||
self.logger.debug("Domain %s." % domain)
|
||||
|
||||
if __name__ == "__main__":
|
||||
prefs = gnuviech.GNVPrefs()
|
||||
|
|
Loading…
Reference in a new issue