├── .gitignore
├── test
└── evalid
│ └── core_test.clj
├── README.md
├── project.clj
├── resources
└── logback.xml
└── src
└── evalid
└── core.clj
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | /logs
5 | /out.edn
6 | pom.xml
7 | pom.xml.asc
8 | *.jar
9 | *.class
10 | /.lein-*
11 | /.nrepl-port
12 |
--------------------------------------------------------------------------------
/test/evalid/core_test.clj:
--------------------------------------------------------------------------------
1 | (ns evalid.core-test
2 | (:require [clojure.test :refer :all]
3 | [evalid.core :refer :all]))
4 |
5 | (deftest a-test
6 | (testing "FIXME, I fail."
7 | (is (= 0 1))))
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # evalid
2 |
3 | A Clojure library designed to ... well, that part is up to you.
4 |
5 | ## Usage
6 |
7 | FIXME
8 |
9 | ## License
10 |
11 | Copyright © 2014 FIXME
12 |
13 | Distributed under the Eclipse Public License either version 1.0 or (at
14 | your option) any later version.
15 |
--------------------------------------------------------------------------------
/project.clj:
--------------------------------------------------------------------------------
1 | (defproject evalid "0.1.0-SNAPSHOT"
2 | :description "Validate mailbox using SMTP"
3 | :dependencies [[org.clojure/clojure "1.7.0-alpha2"]
4 | [nettyca "0.1.0-SNAPSHOT"]
5 | [ch.qos.logback/logback-classic "1.1.2"]]
6 | :main evalid.core
7 | :aot [evalid.core])
8 |
--------------------------------------------------------------------------------
/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %date %6level [%32thread] %-15logger{15} %msg%n
6 |
7 |
8 |
9 |
10 | logs/evalid.log
11 |
12 | logs/old/evalid.%d{yyyy-MM-dd}.log
13 | 3
14 |
15 |
16 | %date %6level [%32thread] %-15logger{15} %msg%n
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/evalid/core.clj:
--------------------------------------------------------------------------------
1 | (ns evalid.core
2 | (:require [nettyca.core :as nc]
3 | [clojure.tools.logging :as log]
4 | [clojure.core.async :refer [chan timeout go go-loop alts!
5 | ! close!] :as async])
6 | (:gen-class))
7 |
8 | (defmacro lwrite [c s n]
9 | `(do (log/info "smtp: writ:" ~s)
10 | (let [[v# c#] (alts! [[~c (str ~s "\r\n")] (timeout ~n)])]
11 | (identical? c# ~c))))
12 |
13 | (defmacro lread [c n]
14 | `(let [[v# c#] (alts! [~c (timeout ~n)])]
15 | (log/info "smtp: read:" v#)
16 | v#))
17 |
18 | (defn rvalid? [s] (and s (.startsWith s "2")))
19 |
20 | (defn smtp-client [rcpt domain]
21 | (fn [r w c]
22 | (go (let [r0 (lread r 5000)
23 | w0 (when (rvalid? r0)
24 | (lwrite w (format "helo %s" domain) 5000))
25 | r1 (when w0 (lread r 5000))
26 | w1 (when (rvalid? r1)
27 | (lwrite w "mail from: " 5000))
28 | r2 (when w1 (lread r 5000))
29 | w2 (when (rvalid? r2)
30 | (lwrite w (format "rcpt to: <%s>" rcpt) 5000))
31 | r3 (when w2 (lread r 15000))
32 | rz (first (drop-while nil? [r3 r2 r1 r0]))]
33 | (log/info "smtp: done:" rcpt "->" rz)
34 | (close! r) (close! w) (close! c)))))
35 |
36 | (defn btake [c]
37 | (let [[nc v] (async/alts!! [c (timeout 10000)])]
38 | (identical? c nc)))
39 |
40 | (defn verify [{:keys [e m]} domain]
41 | (log/info "contacting mx:" m ", for email:" e)
42 | (nc/start m 25 (smtp-client e domain) :client))
43 |
44 | (def verify-and-wait
45 | (comp btake :go-chan verify))
46 |
47 | ;; out.edn is list of maps like: {:m mx-server :e email}
48 |
49 | (defn grab []
50 | (read-string (slurp "out.edn")))
51 |
52 | (defn -main [& args]
53 | (let [xs (grab)]
54 | (log/info "working on records:" (count xs))
55 | (doseq [x xs]
56 | (when (:m x)
57 | (verify-and-wait x (first args))))))
58 |
59 | (comment
60 |
61 | (def gs (grab))
62 | (last gs)
63 |
64 | (verify (last gs) "bar.com")
65 | (verify-and-wait (last gs) "bar.com")
66 |
67 | )
68 |
--------------------------------------------------------------------------------