summaryrefslogtreecommitdiff
path: root/mail/deliver
blob: 5aeeda2e4f20c1efa633601fc3a86c55e1724f7a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/local/bin/python

# Heh, heh, heh, this partition reminds me of the knapsack problem ;-)
# Ie, the optimal distribution here is NP Complete.

import os

if not os.fork():
    import string, sys, regsub
    sys.path.append('/home/mailman/mailman/modules')
    import mm_cfg
    def CallSendmail(cmd, stdin):
	file = os.popen(cmd, 'w')
	file.write(stdin)
	file.close()

    domain_info = {}
    def GroupByDomain(addr):
	parts = regsub.split(addr, '[.@]')
	key = string.join(parts[-2:])
	if not domain_info.has_key(key):
	    domain_info[key] = [addr]
	else:
	    domain_info[key].append(addr)

    def BuildGroups(biglist, num_addrs):
	biglist.sort(lambda x,y: len(x) < len(y))
	groups = []
	for i in range(spawns-1):
	    target_size = num_addrs / (spawns - i)
	    if not len(biglist):
		break
	    newlist = biglist[0]
	    biglist.remove(biglist[0])
	    j = 0
	    while len(newlist) < target_size:
		if j >= len(biglist):
		    break
		if len(newlist) + len(biglist[j]) > target_size:
		    j = j + 1
		    continue
		newlist = newlist + biglist[j]
		biglist.remove(biglist[j])
	    groups.append(newlist)
	    num_adders = num_addrs - len(newlist)
	lastgroup = []
	for item in biglist:
	    lastgroup = lastgroup + item
	if len(lastgroup):
	    groups.append(lastgroup)
	return groups

    def CallSendmailForEachGroup(groups, sender, text):
	for group in groups:
	    if not os.fork():
		CallSendmail(mm_cfg.SENDMAIL_CMD %
			     (sender, string.join(group)), text)
		os._exit(0)

    sender = sys.argv[2]
    spawns = eval(sys.argv[3])
    if spawns > mm_cfg.MAX_SPAWNS:
	spawns = mm_cfg.MAX_SPAWNS
    if spawns < 1:
	spawns = 1
    to_list = sys.argv[4:]
    try:
        file = open(sys.argv[1], 'r')
    except IOError, msg:
        raise IOError, (msg[0], msg[1], sys.argv[1])
    text = file.read()
    file.close()
    os.unlink(sys.argv[1])

    map(GroupByDomain, to_list)
    final_groups = BuildGroups(domain_info.values(), len(to_list))
    
    CallSendmailForEachGroup(final_groups, sender, text)