3

I want to validate a email using clojure. How can I do it.

(defn validate-email [email]

    )

I want to know how will be the function body writeen using regular expressions.

Manish Singh
  • 151
  • 1
  • 10
  • 1
    Have a look at [Using a regular expression to validate an email address](http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address) – Leonid Beschastny Nov 16 '15 at 13:34
  • i am new to clojure. I am not able to write correct syntax for email verification – Manish Singh Nov 16 '15 at 14:00
  • 1
    The downvotes are outright silly. This is a beginner question and it has a larger number of views that other recent #clojure questions. – Marcin Bilski Nov 16 '15 at 20:48
  • 1
    Though I didn't downvote this, but it would be a lot better if you state what you have tried/learned and why they don't work. – Davyzhu Nov 17 '15 at 02:19
  • Manish, to add to what Davyzhu wrote, you seem to be asking us to write your code from you from the very beginning of your task. First you have to try to write it yourself. You can ask for help on the next step, you can ask for help when you get stuck, you can even ask for help on how to think about what to do next. You have to do some work first. If you are learning Clojure, you have to do some work to learn some Clojure first, and show us what you tried to do, and tell us what didn't work. – Mars Nov 17 '15 at 05:54

5 Answers5

5

Here is an example of a simple function that will check input email string against simple regexp:

(defn validate-email [email]
  (re-matches #".+\@.+\..+" email))

It will return input email if it matches .+\@.+\..+ regexp and nil otherwise:

(validate-email "foo@bar.baz") ;=> "foo@bar.baz"
(validate-email "invalid") ;=> nil
(if (validate-email "foo@bar.baz") :valid :invalid) ;=> :valid
(if (validate-email "invalid") :valid :invalid) ;=> :invalid

And if you need a good regexp to match emails against, see Using a regular expression to validate an email address.

Community
  • 1
  • 1
Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
2
(defn validate-email
  [email]
  (let [pattern #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"]
    (and (string? email) (re-matches pattern email))))

As far as regular expressions in Clojure, this might help: http://www.lispcast.com/clojure-regex


Or, funcool/struct can be used to validate email, beside other things.

Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133
Marcin Bilski
  • 572
  • 6
  • 13
  • `re-matches` always looks for complete matches, so there is no need to add either `^` or `$` with it. – Leonid Beschastny Nov 16 '15 at 14:22
  • Thanks, the line was certainly pretty long. :) As far as `and` vs. `when` are concerned I on the side of the fence which prefers to use `when` for a single condition. While less lispish, it's more intuitive for newbies that I work with. A matter of taste certainly. We can also go ahead and add a precondition because it better expresses the intent in this case. ;) – Marcin Bilski Nov 16 '15 at 15:46
1

Note that using a regular expression to identify 'good' or legitimate email addresses is notoriously difficult to get right. There are a number of edge cases which are easily overlooked. It has gotten a lot easier since some of the more arcane mail routing approaches have dropped out of use, but it can still be tricky.

My advice would be to use something like bouncer which is a validation library which can be used on both the client and server side i.e. for clojure or clojurescript. It has built-in support for email validation. There are numerous other libs which do a similar thing.

This will get you up and running. You can also look at the source code to learn one way this problem can be solved. Later, once you have more experience, you can try doing something similar (but better :-) yourself

Tim X
  • 4,158
  • 1
  • 20
  • 26
1

Clojure has a very useful validation library, i.e. the valip library
If you watch into the predicates.clj file, you can see that there are the email-address? and valid-email-domain? functions and those are exactly for your porpuse. So you can use it as follows

(defn validate-email [email] (valid-email-domain? email))

You can use valid-email-domain for both clojure, and email-address for both clojure and clojurescript.
Here it's the link:
https://github.com/weavejester/valip/blob/master/src/valip/predicates.clj
with other useful validation functions.

0

There are plenty of discussions on SO and elsewhere of how to match email addresses with regular expressions. It seems to me that what you're asking is how to use regular expressions in Clojure.

The reader recognizes #" as starting a literal regular expression, ending in ". Example: #"(t)+".

You can also use re-pattern to compile a regular expression from a string, so you could dynamically create a regular expression pattern like so: (re-pattern (str "^" my-var "$")).


If you are trying to use a regular expression to match a string in its entirety, you can use re-matches. It returns nil (no match), the original string (it matches), or a vector of [full-string, capture-1, capture-2, ...]

(re-matches #"abc" "abcdefg") ;; => nil
(re-matches #"abc.*" "abcdefg") ;; => "abcdefg"
(re-matches #"abc(.)(.*)" "abcdefg") ;; => ["abcdefg", "d", "efg"]

re-matcher takes a regular expression and a string and returns a java.util.regex.Matcher. You can use the find() method to get the next match, or you can use Clojure's re-find.

(def my-matcher (re-matcher #"[aeiou].[aeiou]" "alienate"))
(re-find my-matcher) ;; => "ali"
(re-find my-matcher) ;; => "ena"
(re-find my-matcher) ;; => nil

If you are using a Matcher, then you can use re-groups to get the groups from the most recent match.


Another use of re-find is with a regular expression and a string to return only the first match:

(re-find #"[aeiou].[aeiou]" "alienate") ;; => "ali"

For many cases, you will find re-seq to be a more convenient alternative to re-find with re-matcher. It returns a lazy sequence of all matches:

(re-seq #"[aeiou].[aeiou]" "alienate") ;; => ("ali", "ena"), lazily

Finally, you can search and replace with replace and replace-first. re-quote-replacement helps with the annoying matter of escaping characters correctly.

galdre
  • 2,319
  • 17
  • 31