2012-08-29 32 views
6

Trong email, có vẻ như trường "từ" hoặc "đến" có thể chứa một hoặc nhiều địa chỉ, mỗi địa chỉ có thể giống như "[email protected]" hoặc "John D Jr <[email protected]>"Địa chỉ email phân tích cú pháp cho các trường "từ" và "đến" trong Ruby

vì vậy, một "từ" lĩnh vực thể trông giống như bất kỳ những điều sau đây:

"[email protected]" 

"[email protected], Bob Blue <[email protected]>" 

"Abe Allen <[email protected]>, [email protected]" 

"Abe Allen <[email protected]>, Bob Blue <[email protected]>" 

"Abe Allen <[email protected]>, Bob Blue <[email protected]>, [email protected]" 

và vân vân.

Tôi muốn phân tích cú pháp các trường này, trích xuất từng địa chỉ email nếu địa chỉ hợp lệ và tên nếu nó có mặt. Vì tôi không quen thuộc với tiêu chuẩn email, tôi có thể thiếu một số trường hợp của các trường địa chỉ có thể trông như thế nào. Có một thư viện Ruby có thể làm điều này không?

+1

Phân tích và xác thực địa chỉ email không phải là một nhiệm vụ tầm thường. Phạm vi của các định dạng là rất lớn, và ngay cả khi một địa chỉ là hợp lệ, nó dễ dàng có thể là nó không có thật và không phải là một địa chỉ giao hàng. Xem "[Tôi biết cách xác thực địa chỉ email cho đến khi tôi đọc RFC] (http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address- cho đến khi-i.aspx) "cho một bài viết thú vị về chủ đề này. Ngoài ra [bài viết của Wikipedia] (http://en.wikipedia.org/wiki/Email_address) và [SMTP RFC] (http://tools.ietf.org/html/rfc5322). –

Trả lời

11

Vâng, có một viên ngọc cho điều này; nó được gọi là mail.

require 'mail' 

addresses = [] 
raw_addresses = Mail::AddressList.new("Abe Allen <[email protected]>, Bob Blue <[email protected]>, [email protected]") 

raw_addresses.addresses.each do |a| 
    address = {} 

    address[:address] = a.address 
    address[:name] = a.display_name if a.display_name.present? 

    addresses << address  
end 
+1

Cảm ơn, điều này hoạt động tốt cho trường hợp sử dụng của tôi. Btw, tôi nghĩ bạn muốn làm "raw_addresses.addresses.each"? – foobar

+0

Yup, cảm ơn bạn. – deefour

0

Giả sử dữ liệu của bạn sau những ví dụ bạn đưa ra, điều này sẽ làm việc:

def extract_emails(string) 
    string.split(', ').map do |user_string| 
    if user_string.include? '<' 
     user_string =~ /^([^<]*)<([^>]*)>$/ 
     {user: $1.strip, email: $2} 
    else 
     {user: nil, email: user_string} 
    end 
    end 
end 

extract_emails "[email protected]"           
# => [{:user=>nil, :email=>"[email protected]"}] 

extract_emails "[email protected], Bob Blue <[email protected]>"      
# => [{:user=>nil, :email=>"[email protected]"}, {:user=>"Bob Blue", :email=>"[email protected]"}] 

extract_emails "Abe Allen <[email protected]>, [email protected]"      
# => [{:user=>"Abe Allen", :email=>"[email protected]"}, {:user=>nil, :email=>"[email protected]"}] 

extract_emails "Abe Allen <[email protected]>, Bob Blue <[email protected]>"   
# => [{:user=>"Abe Allen", :email=>"[email protected]"}, {:user=>"Bob Blue", :email=>"[email protected]"}] 

extract_emails "Abe Allen <[email protected]>, Bob Blue <[email protected]>, [email protected]" 
# => [{:user=>"Abe Allen", :email=>"[email protected]"}, {:user=>"Bob Blue", :email=>"[email protected]"}, {:user=>nil, :email=>"[email protected]"}] 
+0

OP cho biết "Tôi không quen thuộc với tiêu chuẩn email, tôi có thể thiếu một số trường hợp của trường địa chỉ." ... –

+0

Chắc chắn, trừ khi email hoặc tên người dùng của anh ấy có "<" and ">", điều này sẽ hoạt động tốt với tất cả dữ liệu. Nếu họ có thể bao gồm những điều này, thì về cơ bản anh ta sẽ phải viết một trình phân tích cú pháp. –

0

Tôi không biết thư viện, nhưng nếu bạn đang cố gắng để có được danh sách các email bạn có thể tự làm như sau. (Long winded on purpose)

@a = "Abe Allen <[email protected]>, Bob Blue <[email protected]>, [email protected]" 
b = @a.split(',') #=> ["Abe Allen <[email protected]>", " Bob Blue <[email protected]>", " [email protected]"] 
c = b.collect{|x| x[/<(.*?)>|^([^<>]*)$/]} #=> ["<[email protected]>", "<[email protected]>", " [email protected]"] 
d = c.gsub(/[<>]/,'') #=> ["[email protected]", "[email protected]", " [email protected]"] 

Nếu bạn muốn khớp với tên và địa chỉ email của họ, bạn sẽ cần một cái gì đó khác.

Ngoài ra, điều này sẽ không hoạt động nếu có '<' hoặc '>' trong địa chỉ email, nhưng điều đó không phổ biến.

Các vấn đề liên quan