This file is indexed.

/usr/bin/mandrill is in python-mandrill 1.0.57-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  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
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#! /usr/bin/python
'''Mandrill

Usage:
    mandrill setup
    mandrill [-v] ping [--count=<cnt>]
    mandrill [-v] send [--from=<addr>] [--to=<addr>] [--subject=<subj>] [--text-only]
    mandrill [-v] search [--json] <query>
    mandrill --help

Options:
    -h --help           Show this screen.
    -v                  Turn on verbose mode - all traffic to the API will be logged to STDERR
    -V --version        Show version.
    -c --count=<cnt>    The number of times to ping Mandrill.
    -f --from=<addr>    The from address of the message to send.
    -t --to=<addr>      The recipient address of the message to send.
    -s --subject=<subj> The subject line of the message to send.
    --text-only         The message will be sent as plain-text.  If this option is not provided, HTML is presumed.
    -j --json           Print the result as a JSON string
'''
import mandrill, docopt, time, sys, os.path, socket, math, re, subprocess, tempfile
try:
    import json as json
except:
    import simplejson as json

email_re = re.compile(r'^[^\"\s@<>(),]+@[a-z0-9][a-z0-9\.\-_]*\.[a-z]+$', re.I)

def command_setup(args):
    global m
    apikey = raw_input('Your Mandrill API Key: ')
    try:
        m = mandrill.Mandrill(apikey)
        m.users.ping()
    except mandrill.Error, e:
        print('Got an error trying to use that API key: %s' % e)
        sys.exit(1)
    
    try:
        f = open('/etc/mandrill.key', 'w')
        f.write(apikey)
        f.close()
        print('Saved Mandrill API Key to /etc/mandrill.key')
    except:
        f = open(os.path.expanduser('~/.mandrill.key'), 'w')
        f.write(apikey)
        f.close()
        print('Saved Mandrill API Key to %s' % os.path.expanduser('~/.mandrill.key'))


def command_ping(args):
    print('PING https://mandrillapp.com/api/1.0/users/ping2.json')
    if args['--count'] is None:
        args['--count'] = 4
    else:
        args['--count'] = int(args['--count'])
    
    times = []
    error_count = 0
    for i in range(args['--count']):
        start = time.time()
        try:
            m.users.ping2()
            (remote_addr, remote_port) = m.last_request['remote_addr']
            reverse_addr = socket.gethostbyaddr(remote_addr)[0]
            times.append(m.last_request['time'] * 1000)

            print('%d bytes from %s (%s): req=%s port=%s time=%.2fms' % (len(m.last_request['response_body']), reverse_addr, remote_addr, i + 1, remote_port, m.last_request['time'] * 1000))
        except mandrill.Error, e:
            error_count += 1
            (remote_addr, remote_port) = m.last_request['remote_addr']
            reverse_addr = socket.gethostbyaddr(remote_addr)[0]
            times.append(m.last_request['time'] * 1000)
            
            print('%d bytes from %s (%s): req=%s port=%s time=%.2fms ERROR: %s' % (len(m.last_request['response_body']), reverse_addr, remote_addr, i + 1, remote_port, m.last_request['time'] * 1000, e))

        if i < args['--count'] - 1: time.sleep(1)
    
    sq_sum = sum([t * t for t in times])
    mean = sum(times) / len(times)
    stdev = math.sqrt((sq_sum / len(times)) - (mean * mean))
    print('\n--- Mandrill ping statistics ---')
    print('%d calls transmitted, %d received, %d%% error rate, time %dms' % (args['--count'], args['--count'] - error_count, float(error_count) / args['--count'] * 100, sum(times)))
    print('rtt min/avg/max/mdev = %.3f/%.3f/%.3f/%.3f ms' % (min(times), mean, max(times), stdev))


def command_send(args):
    if args['--from'] is not None and not email_re.match(args['--from']):
        args['--from'] = None

    if args['--to'] is not None and not email_re.match(args['--to']):
        args['--to'] = None

    while args['--from'] is None:
        from_email = raw_input('From: ').strip()
        if email_re.match(from_email):
            args['--from'] = from_email
        else:
            print('Invalid email address. Try again.')

    while args['--to'] is None:
        to_email = raw_input('To: ').strip()
        if email_re.match(to_email):
            args['--to'] = to_email
        else:
            print('Invalid email address. Try again.')

    while args['--subject'] is None:
        subject = raw_input('Subject: ').strip()
        if subject != '':
            args['--subject'] = subject
        else:
            print('Enter a subject line.')

    if sys.stdin.isatty():
        editor = os.environ.get('EDITOR', 'vim')
        if args['--text-only']:
            suffix = '.txt'
        else:
            suffix = '.html'

        with tempfile.NamedTemporaryFile(suffix=suffix) as tmp:
            if args['--text-only']:
                tmp.write('REMOVE this and replace with your text content.')
            else:
                tmp.write('<p>REMOVE this and replace with your HTML content.</p>')
            tmp.flush()

            subprocess.check_call([editor, tmp.name])
            tmp.seek(0)
            content = tmp.read()
            if 'REMOVE this and replace with your' in content:
                print('Send canceled')
                sys.exit(1)
    else:
        content = sys.stdin.read()

    msg = {'from_email': args['--from'], 'to': [{'email': args['--to']}], 'subject': args['--subject']}
    if args['--text-only']:
        msg['text'] = content
    else:
        msg['html'] = content

    m.messages.send(msg)


def command_search(args):
    query = args['<query>']
    results = m.messages.search(query)
    if args['--json']:
        json.dump(results, sys.stdout)
    else:
        print('Time\tStatus\tSender\tEmail\tSubject\tOpens\tClicks')
        for result in results:
            print('%s\t%s\t%s\t%s\t%s\t%s\t%s' % (time.strftime('%d/%b/%Y %H:%M:%S %Z', time.localtime(result['ts'])), result['state'], result['sender'], result['email'], result['subject'], result['opens'], result['clicks']))


if __name__  == '__main__':
    arguments = docopt.docopt(__doc__, version='Mandrill 1.0')
    if not arguments['setup']:
        try:
            m = mandrill.Mandrill(debug=arguments['-v'])
        except mandrill.Error:
            print('This looks like the first time you\'ve run Mandrill, so let\'s get you set up.')
            command_setup(arguments)

    commands = dict([(k[8:], getattr(sys.modules['__main__'], k)) for k in dir(sys.modules['__main__']) if k.startswith('command_')])
    for command, func in commands.items():
        if command in arguments and arguments[command]:
            try:
                func(arguments)
                sys.exit(0)
            except Exception, e:
                print(e)
                sys.exit(1)