22

I need to write a function for a project i'm working on for fun, where we're making a site only accessible to students, staff, and alumni at an institution.

Let's say the schools website is: school.edu.

I'm having trouble writing a php filter that checks that the submitted email address has the domain of "school.edu"

I'll use an example. Dude #1 has an email of user@mail.com and Dude #2 has an email at user@school.edu. I want to make sure that Dude 1 gets an error message, and Dude #2 has a successful registration.

That's the gist of what I'm trying to do. In the near future the site will allow registration by another two locale schools: school2.edu and school3.edu. I will then need the checker to check the email against a small list (maybe an array?) of domains to verify that the email is of a domain name on the list.

Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
Phil
  • 221
  • 1
  • 2
  • 3
  • 1
    And what have you come up with? Have you started writing anything at all, or researching [php's regular expressions](http://php.net/manual/en/book.regex.php), for instance? Also what about academic registrants from other countries, such as the UK (with the `.ac.uk` tld)? – David Thomas Aug 02 '11 at 19:07
  • mark@fb.com - he might have some pointers for you...or maybe you could get ahold of one of the winklevi, they have some experience here. – Jim Rubenstein Aug 02 '11 at 19:23
  • Right now its just for some local schools. We're almost done coding the whole site. Just adding some final features, such as the email validation script. – Phil Aug 02 '11 at 19:27
  • And Jim, as much as I'd love to pick Mark's brain on coding and stuff, I doubt he has his email publicly available. Sadly. – Phil Aug 02 '11 at 19:34
  • Phil, use @jim to let him know he's been mentioned – Rag Aug 02 '11 at 19:45

7 Answers7

41

There's a few ways to accomplish this, here's one:

// Make sure we have input
// Remove extra white space if we do
$email = isset($_POST['email']) ? trim($_POST['email']) : null;

// List of allowed domains
$allowed = [
    'school.edu',
    'school2.edu',
    'school3.edu'
];

// Make sure the address is valid
if (filter_var($email, FILTER_VALIDATE_EMAIL))
{
    // Separate string by @ characters (there should be only one)
    $parts = explode('@', $email);

    // Remove and return the last part, which should be the domain
    $domain = array_pop($parts);

    // Check if the domain is in our list
    if ( ! in_array($domain, $allowed))
    {
        // Not allowed
    }
}
Wesley Murch
  • 101,186
  • 37
  • 194
  • 228
  • 1
    Just as an added suggestion, and this probably for all text inputs, remember to run trim() on your submitted values, in case someone adds a space at the end of the email address – thorne51 Dec 15 '14 at 07:20
11

You can use regex:

if(preg_match('/^\w+@school\.edu$/i', $source_string) > 0)
    //valid

Now proceed to tear me apart in the comments because there's some crazy email address feature I didn't account for :)

Rag
  • 6,405
  • 2
  • 31
  • 38
5

Note that just getting everything after the @ may not accomplish what you are trying to accomplish because of email addresses like user@students.ecu.edu. The get_domain function below will only get the domain down to the second level domain. It will return "unc.edu" for username@unc.edu or username@mail.unc.edu. Also, you may want to account for domains with country codes (which have top level domains of 2 characters).

You can use the function below to extract the domain. Then you can use an array of school domains, or put the school domains in a database and check the email address against that.

    function get_domain($email)
    {
       if (strrpos($email, '.') == strlen($email) - 3)
          $num_parts = 3;
       else
          $num_parts = 2;

       $domain = implode('.',
            array_slice( preg_split("/(\.|@)/", $email), - $num_parts)
        );

        return strtolower($domain);
    }


    // test the function
    $school_domains = array('unc.edu', 'ecu.edu');

    $email = 'someone@students.ecu.edu';

    if (in_array(get_domain($email), $school_domains))
    {
        echo "good";
    }
dougd_in_nc
  • 371
  • 5
  • 20
4

If you are using Laravel:

Str::endsWith($email, '@foo.bar.edu'); // bool
ahinkle
  • 2,117
  • 3
  • 29
  • 58
3

I'd just do this:

 $acceptedDomains = array('site1.edu', 'site2.edu');

 if(in_array(substr($email, strrpos($email, '@') + 1), $acceptedDomains))
 {
    // Email is from a domain in $acceptedDomains
 }

The 'whatever.edu' portion will always be after the @. So, all you need to do is:

  1. Find the last occurrence of @ in the string. (In a normal email, there will only be one, but that doesn't matter here.)
  2. Get the portion of the email after the @. This will be the domain name.
  3. Use in_array() to compare the domain name against a list of accepted domains in $acceptedDomains.

Note that if you want to also accept emails from email@any.subdomain.site1.edu, you'd have to do just a little more, but that may or may not be applicable here. I'm also assuming you've validated that the email addresses are well formed before doing this.

Chris Hepner
  • 1,552
  • 9
  • 16
2

Simple and Single line:

     list($name, $domain) = explode('@', $email);
Dumindu Perera
  • 1,571
  • 15
  • 13
0

You could always do something like this:

$good_domains = array('school.edu'); //in the future, just add to this array for more schools

$email = "user@school.edu"; //your user's email

$matches = array();
preg_match("/^(.+)@([^\(\);:,<>]+\.[a-zA-Z]+)/", $email, &$matches); //validates the email and gathers information about it simultaneously
//should return ['user@mail.com', 'user', 'mail.com']
$domain = $matches[3];

if(in_array($domain, $goood_domains))
{
    //success! your user is from school.edu!
}
else
{
    //oh no! an imposter!
}
Patrick Perini
  • 22,555
  • 12
  • 59
  • 88