import_users_from_csv.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Script takes a CSV list of users and does a 'bulk' insertion into mysql.
  4. #
  5. # Copyright (C) 2009 Simone Piccardi
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or (at
  10. # your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful, but
  13. # WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. # General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. #
  21. import csv
  22. import getopt
  23. import sys
  24. import re
  25. import time
  26. import random, string
  27. from datetime import datetime
  28. from crypt import crypt
  29. try:
  30. import MySQLdb
  31. except ImportError ,e:
  32. print 'Cannot import the needed MySQLdb module, you must install it'
  33. print 'on Debian systems just use the command'
  34. print ' apt-get install python-mysqldb'
  35. def usage():
  36. print "Usage: inspostadmusers.py [options] users.csv"
  37. print " -h print this help"
  38. print " -t test run, do not insert, just print"
  39. print " -u DB user"
  40. print " -p DB password"
  41. print " -D DB name"
  42. print " -H DB host"
  43. print " -q Quota in Mb (0 => no limit)"
  44. print " -n char in seed"
  45. print " -d debug info on"
  46. print " -A create default alias for each domain"
  47. print
  48. print "the users.csv file must contains the user list with a line"
  49. print "for each user, first line should be a title line with at least"
  50. print "the following column names: "
  51. print " * user - user part of the email (like user in user@domain.com)"
  52. print " * password - cleartext password"
  53. print " * domain - domain name (like 'domain.com')"
  54. print " * name - full user name ('Name Surname')"
  55. print
  56. print "the 'name' column is optional, other columns will be ignored"
  57. print
  58. print "Known restrictions:"
  59. print "* this script only works with MySQL"
  60. print "* mailbox paths are hardcoded to domain/username/"
  61. # option parsing
  62. try:
  63. opts, args = getopt.getopt(sys.argv[1:], 'u:p:d:D:H:htdA')
  64. optval={}
  65. for opt, val in opts:
  66. if opt == "-h":
  67. usage()
  68. sys.exit(0)
  69. else:
  70. optval[opt]=val
  71. except getopt.GetoptError:
  72. usage()
  73. sys.exit(2)
  74. #
  75. # Setup DB connection
  76. #
  77. MYSQLDB="postfixadmin"
  78. MYSQLUSER="postfixadmin"
  79. MYSQLPASSWORD=""
  80. MYSQLHOST="localhost"
  81. # settings by command line options
  82. if optval.has_key('-u'):
  83. MYSQLUSER = optval['-u']
  84. if optval.has_key('-p'):
  85. MYSQLPASSWORD = optval['-p']
  86. if optval.has_key('-D'):
  87. MYSQLDB = optval['-D']
  88. if optval.has_key('-H'):
  89. MYSQLHOST = optval['-H']
  90. if optval.has_key('-q'):
  91. quota = optval['-q']
  92. else:
  93. quota = 0
  94. if optval.has_key('-n'):
  95. seed_len = optval['-n']
  96. else:
  97. seed_len = 8
  98. # check arguments, only the user list file must be present
  99. if len(args) !=1:
  100. print 'Need just one argument'
  101. usage()
  102. sys.exit(1)
  103. # MySQL connection (skipped in test run)
  104. if optval.has_key('-t'):
  105. print "Test Run"
  106. else:
  107. try:
  108. connection = MySQLdb.connect(host=MYSQLHOST, user=MYSQLUSER,
  109. db=MYSQLDB, passwd=MYSQLPASSWORD)
  110. except MySQLdb.MySQLError, e:
  111. print "Database connection error"
  112. print e
  113. sys.exit(1)
  114. cursor = connection.cursor()
  115. #
  116. # Main body
  117. #
  118. NOW = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  119. # read and convert CSV data
  120. lista = csv.DictReader(open(args[0]))
  121. def gen_seed(seed_len, chars):
  122. return '$1$'+''.join([random.choice(chars) for _ in xrange(seed_len)])+'$'
  123. def insert_record(cursor,table,record):
  124. columns = record.keys()
  125. query = "INSERT INTO " + table + "(" + ','.join(columns) + ") VALUES (" + ','.join(len(columns)*['%s']) + ")"
  126. try:
  127. cursor.execute(query, record.values())
  128. return 0
  129. except MySQLdb.MySQLError, e:
  130. print "Database insertion error"
  131. print e
  132. print "Record was:"
  133. print record.values()
  134. print "Query was:"
  135. print query
  136. # defining default values for tables (mailbox, alias and domain)
  137. mailbox = {
  138. 'created': NOW,
  139. 'modified': NOW,
  140. 'active': 1,
  141. 'quota': quota
  142. }
  143. aliases = {
  144. 'created': NOW,
  145. 'modified': NOW,
  146. 'active': 1
  147. }
  148. domain = {
  149. 'description': "",
  150. 'aliases': 0,
  151. 'mailboxes': 0,
  152. 'quota': 0,
  153. 'transport': 'virtual',
  154. 'backupmx': 0,
  155. 'created': NOW,
  156. 'modified': NOW,
  157. 'active': 1
  158. }
  159. # list of default alias
  160. def_alias = ['abuse','hostmaster','postmaster','webmaster']
  161. domain_list = {}
  162. chars = string.letters + string.digits
  163. # loop over the CSV
  164. for row in lista:
  165. # create domain if it does not exists
  166. if domain_list.has_key(row["domain"]):
  167. if optval.has_key('-d'):
  168. print "Domain " + row["domain"] + "already exixts"
  169. else:
  170. domain_list[row["domain"]] = 1
  171. domain['domain'] = row["domain"]
  172. if optval.has_key('-t'):
  173. print "Inserting domain"
  174. print domain
  175. else:
  176. insert_record(cursor,'domain',domain)
  177. if optval.has_key('-A'):
  178. for i in def_alias:
  179. aliases['address']= i+'@'+row["domain"]
  180. aliases['goto']= aliases['address']
  181. aliases['domain'] = row["domain"]
  182. if optval.has_key('-t'):
  183. print "Inserting alias"
  184. print aliases
  185. else:
  186. insert_record(cursor,'alias',aliases)
  187. # build query data for mailbox table
  188. mailbox['username']=row["user"]+'@'+row["domain"]
  189. encpass=crypt(row["password"], gen_seed(seed_len,chars))
  190. mailbox['password'] = encpass
  191. mailbox['name'] = row["name"]
  192. mailbox['maildir'] = row["domain"]+'/'+row["user"]+'/'
  193. mailbox['local_part'] =row["user"]
  194. mailbox['domain'] = row["domain"]
  195. # build query data for alias table
  196. aliases['address']= mailbox['username']
  197. aliases['goto']= mailbox['username']
  198. aliases['domain'] = row["domain"]
  199. # inserting data for mailbox (and relate alias)
  200. if optval.has_key('-t'):
  201. print "Inserting mailbox"
  202. print mailbox
  203. print aliases
  204. else:
  205. insert_record(cursor,'mailbox',mailbox)
  206. insert_record(cursor,'alias',aliases)
  207. sys.exit(0)