diff --git a/app/models/channel/email_build.rb b/app/models/channel/email_build.rb new file mode 100644 index 000000000..718bd4a3f --- /dev/null +++ b/app/models/channel/email_build.rb @@ -0,0 +1,45 @@ +require 'mail' + +class Channel::EmailBuild + + def build(attr, notification = false) + mail = Mail.new + + # set organization + organization = Setting.get('organization') + if organization then; + mail['organization'] = organization.to_s + end + + # notification + if notification + attr['X-Loop'] = 'yes' + attr['Precedence'] = 'bulk' + attr['Auto-Submitted'] = 'auto-generated' + end + + # set headers + attr.each do |key, v| + if key.to_s != 'attachments' && key.to_s != 'body' + mail[key.to_s] = v.to_s + end + end + + # add body + mail.text_part = Mail::Part.new do + body attr[:body] + end + + # add attachments + if attr[:attachments] + attr[:attachments].each do |attachment| + mail.attachments[attachment.filename] = { + :content_type => attachment.preferences['Content-Type'], + :mime_type => attachment.preferences['Mime-Type'], + :content => attachment.store_file.data + } + end + end + return mail + end +end \ No newline at end of file diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb new file mode 100644 index 000000000..8abc545c3 --- /dev/null +++ b/app/models/channel/email_parser.rb @@ -0,0 +1,127 @@ +require 'mail' + +class Channel::EmailParser + + def parse (channel, msg) + mail = Mail.new( msg ) + from_email = Mail::Address.new( mail[:from].value ).address + from_display_name = Mail::Address.new( mail[:from].value ).display_name + + # use transaction + ActiveRecord::Base.transaction do + + user = User.where( :email => from_email ).first + if !user then + puts 'create user...' + roles = Role.where( :name => 'Customer' ) + user = User.create( + :login => from_email, + :firstname => from_display_name, + :lastname => '', + :email => from_email, + :password => '', + :active => true, + :roles => roles, + :created_by_id => 1 + ) + end + + # set current user + UserInfo.current_user_id = user.id + + def conv (charset, string) + if charset == 'US-ASCII' then + charset = 'LATIN1' + end + Iconv.conv("UTF8", charset, string) + end + + # get ticket# from subject + ticket = Ticket.number_check( mail[:subject].value ) + + # set ticket state to open if not new + if ticket + ticket_state = Ticket::State.find( ticket.ticket_state_id ) + ticket_state_type = Ticket::StateType.find( ticket_state.ticket_state_type_id ) + if ticket_state_type.name != 'new' + ticket.ticket_state = Ticket::State.where( :name => 'open' ).first + ticket.save + end + end + + # create new ticket + if !ticket then + ticket = Ticket.create( + :group_id => channel[:group_id], + :customer_id => user.id, + :title => conv(mail['subject'].charset || 'LATIN1', mail['subject'].to_s), + :ticket_state_id => Ticket::State.where(:name => 'new').first.id, + :ticket_priority_id => Ticket::Priority.where(:name => '2 normal').first.id, + :created_by_id => user.id + ) + end + + # import mail + plain_part = mail.multipart? ? (mail.text_part ? mail.text_part.body.decoded : nil) : mail.body.decoded + # html_part = message.html_part ? message.html_part.body.decoded : nil + article = Ticket::Article.create( + :created_by_id => user.id, + :ticket_id => ticket.id, + :ticket_article_type_id => Ticket::Article::Type.where(:name => 'email').first.id, + :ticket_article_sender_id => Ticket::Article::Sender.where(:name => 'Customer').first.id, + :body => conv(mail.body.charset || 'LATIN1', plain_part), + :from => mail['from'] ? conv(mail['from'].charset || 'LATIN1', mail['from'].to_s) : nil, + :to => mail['to'] ? conv(mail['to'].charset || 'LATIN1', mail['to'].to_s) : nil, + :cc => mail['cc'] ? conv(mail['cc'].charset || 'LATIN1', mail['cc'].to_s) : nil, + :subject => mail['subject'] ? conv(mail['subject'].charset || 'LATIN1', mail['subject'].to_s) : nil, + :message_id => mail['message_id'] ? mail['message_id'].to_s : nil, + :internal => false + ) + + # store mail plain + Store.add( + :object => 'Ticket::Article::Mail', + :o_id => article.id, + :data => msg, + :filename => 'plain.msg', + :preferences => {} + ) + + # store attachments + if mail.attachments + mail.attachments.each do |attachment| + + # get file preferences + headers = {} + attachment.header.fields.each do |f| + headers[f.name] = f.value + end + headers_store = {} + headers_store['Mime-Type'] = attachment.mime_type + if attachment.charset + headers_store['Charset'] = attachment.charset + end + ['Content-ID', 'Content-Type'].each do |item| + if headers[item] + headers_store[item] = headers[item] + end + end + + # store file + Store.add( + :object => 'Ticket::Article', + :o_id => article.id, + :data => attachment.body.decoded, + :filename => attachment.filename, + :preferences => headers_store + ) + end + end + + return true + end + + # execute ticket events + Ticket::Observer::Notification.transaction + end +end \ No newline at end of file diff --git a/app/models/channel/imap.rb b/app/models/channel/imap.rb index 748af989d..c679a0aa5 100644 --- a/app/models/channel/imap.rb +++ b/app/models/channel/imap.rb @@ -1,148 +1,28 @@ -require 'mail' require 'net/imap' -class Channel::IMAP +class Channel::IMAP < Channel::EmailParser include UserInfo - def fetch (account) + def fetch (channel) puts 'fetching imap' - imap = Net::IMAP.new(account[:options][:host], 993, true ) - imap.authenticate('LOGIN', account[:options][:user], account[:options][:password]) + imap = Net::IMAP.new(channel[:options][:host], 993, true ) + imap.authenticate('LOGIN', channel[:options][:user], channel[:options][:password]) imap.select('INBOX') + count = 0 imap.search(['ALL']).each do |message_id| msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822'] - puts '--------------------' # puts msg.to_s - mail = Mail.new( msg ) - from_email = Mail::Address.new( mail[:from].value ).address - from_display_name = Mail::Address.new( mail[:from].value ).display_name - - # use transaction - ActiveRecord::Base.transaction do - - user = User.where( :email => from_email ).first - if !user then - puts 'create user...' - roles = Role.where( :name => 'Customer' ) - user = User.create( - :login => from_email, - :firstname => from_display_name, - :lastname => '', - :email => from_email, - :password => '', - :active => true, - :roles => roles, - :created_by_id => 1 - ) - end - - # set current user - UserInfo.current_user_id = user.id - - def conv (charset, string) - if charset == 'US-ASCII' then - charset = 'LATIN1' - end - Iconv.conv("UTF8", charset, string) - end - - # get ticket# from subject - ticket = Ticket.number_check( mail[:subject].value ) - - # set ticket state to open if not new - if ticket - ticket_state = Ticket::State.find( ticket.ticket_state_id ) - ticket_state_type = Ticket::StateType.find( ticket_state.ticket_state_type_id ) - if ticket_state_type.name != 'new' - ticket.ticket_state = Ticket::State.where( :name => 'open' ).first - ticket.save - end - end - - # create new ticket - if !ticket then - ticket = Ticket.create( - :group_id => account[:group_id], - :customer_id => user.id, - :title => conv(mail['subject'].charset || 'LATIN1', mail['subject'].to_s), - :ticket_state_id => Ticket::State.where(:name => 'new').first.id, - :ticket_priority_id => Ticket::Priority.where(:name => '2 normal').first.id, - :created_by_id => user.id - ) - end - - # import mail - plain_part = mail.multipart? ? (mail.text_part ? mail.text_part.body.decoded : nil) : mail.body.decoded - # html_part = message.html_part ? message.html_part.body.decoded : nil - article = Ticket::Article.create( - :created_by_id => user.id, - :ticket_id => ticket.id, - :ticket_article_type_id => Ticket::Article::Type.where(:name => 'email').first.id, - :ticket_article_sender_id => Ticket::Article::Sender.where(:name => 'Customer').first.id, - :body => conv(mail.body.charset || 'LATIN1', plain_part), - :from => mail['from'] ? conv(mail['from'].charset || 'LATIN1', mail['from'].to_s) : nil, - :to => mail['to'] ? conv(mail['to'].charset || 'LATIN1', mail['to'].to_s) : nil, - :cc => mail['cc'] ? conv(mail['cc'].charset || 'LATIN1', mail['cc'].to_s) : nil, - :subject => mail['subject'] ? conv(mail['subject'].charset || 'LATIN1', mail['subject'].to_s) : nil, - :message_id => mail['message_id'] ? mail['message_id'].to_s : nil, - :internal => false - ) - - # store mail plain - Store.add( - :object => 'Ticket::Article::Mail', - :o_id => article.id, - :data => msg, - :filename => 'plain.msg', - :preferences => {} - ) - - # store attachments - if mail.attachments - mail.attachments.each do |attachment| - - # get file preferences - headers = {} - attachment.header.fields.each do |f| - headers[f.name] = f.value - end - headers_store = {} - headers_store['Mime-Type'] = attachment.mime_type - if attachment.charset - headers_store['Charset'] = attachment.charset - end - ['Content-ID', 'Content-Type'].each do |item| - if headers[item] - headers_store[item] = headers[item] - end - end - - # store file - Store.add( - :object => 'Ticket::Article', - :o_id => article.id, - :data => attachment.body.decoded, - :filename => attachment.filename, - :preferences => headers_store - ) - end - end - - # delete email from server after article was created - if article - imap.store(message_id, "+FLAGS", [:Deleted]) - end - + # delete email from server after article was created + if parse(channel, msg) + imap.store(message_id, "+FLAGS", [:Deleted]) end - - # execute ticket events - Ticket::Observer::Notification.transaction + count += 1 end imap.expunge() imap.disconnect() - puts 'done' + puts "#{count.to_s} mails fetched. done." end def send(attr, notification = false) channel = Channel.where( :area => 'Email::Outbound', :active => true ).first diff --git a/app/models/channel/pop3.rb b/app/models/channel/pop3.rb index 74f26f209..36f84038a 100644 --- a/app/models/channel/pop3.rb +++ b/app/models/channel/pop3.rb @@ -1,20 +1,34 @@ -#http://blog.ethanvizitei.com/2008/06/using-ruby-for-imap-with-gmail.html +require 'net/pop' +class Channel::POP3 < Channel::EmailParser + include UserInfo -pop = Net::POP3.new("pop.gmail.com", port) -pop.enable_ssl -pop.start('YourAccount', 'YourPassword') -if pop.mails.empty? - puts 'No mail.' -else - i = 0 - pop.each_mail do |m| - File.open("inbox/#{i}", 'w') do |f| - f.write m.pop + def fetch (channel) + puts 'fetching pop3' + + pop = Net::POP3.new( channel[:options][:host], 995 ) + pop.enable_ssl + pop.start( channel[:options][:user], channel[:options][:password] ) + count = 0 + pop.each_mail do |m| + + # delete email from server after article was created + if parse(channel, m.pop) + m.delete + end + count += 1 end - m.delete - i += 1 + pop.finish + puts "#{count.to_s} mails popped. done." end - puts "#{pop.mails.size} mails popped." -end -pop.finish + def send(attr, notification = false) + channel = Channel.where( :area => 'Email::Outbound', :active => true ).first + begin + c = eval 'Channel::' + channel[:adapter] + '.new' + c.send(attr, channel, notification) + rescue Exception => e + puts "can't use " + 'Channel::' + channel[:adapter] + puts e.inspect + end + end +end \ No newline at end of file diff --git a/app/models/channel/sendmail.rb b/app/models/channel/sendmail.rb index 6b4a951cf..81702637b 100644 --- a/app/models/channel/sendmail.rb +++ b/app/models/channel/sendmail.rb @@ -1,48 +1,8 @@ -require 'mail' - -class Channel::Sendmail +class Channel::Sendmail < Channel::EmailBuild include UserInfo def send(attr, channel, notification = false) - mail = Mail.new - - # set organization - organization = Setting.get('organization') - if organization then; - mail['organization'] = organization.to_s - end - - # notification - if notification - attr['X-Loop'] = 'yes' - attr['Precedence'] = 'bulk' - attr['Auto-Submitted'] = 'auto-generated' - end - - # set headers - attr.each do |key, v| - if key.to_s != 'attachments' && key.to_s != 'body' - mail[key.to_s] = v.to_s - end - end - - # add body - mail.text_part = Mail::Part.new do - body attr[:body] - end - - # add attachments - if attr[:attachments] - attr[:attachments].each do |attachment| - mail.attachments[attachment.filename] = { - :content_type => attachment.preferences['Content-Type'], - :mime_type => attachment.preferences['Mime-Type'], - :content => attachment.store_file.data - } - end - end - + mail = build(attr, notification) mail.delivery_method :sendmail mail.deliver - end end \ No newline at end of file diff --git a/app/models/channel/smtp.rb b/app/models/channel/smtp.rb index a38dd9c2b..41889bb20 100644 --- a/app/models/channel/smtp.rb +++ b/app/models/channel/smtp.rb @@ -1,46 +1,7 @@ -require 'mail' - -class Channel::SMTP +class Channel::SMTP < Channel::EmailBuild include UserInfo def send(attr, channel, notification = false) - mail = Mail.new - - # set organization - organization = Setting.get('organization') - if organization then; - mail['organization'] = organization.to_s - end - - # notification - if notification - attr['X-Loop'] = 'yes' - attr['Precedence'] = 'bulk' - attr['Auto-Submitted'] = 'auto-generated' - end - - # set headers - attr.each do |key, v| - if key.to_s != 'attachments' && key.to_s != 'body' - mail[key.to_s] = v.to_s - end - end - - # add body - mail.text_part = Mail::Part.new do - body attr[:body] - end - - # add attachments - if attr[:attachments] - attr[:attachments].each do |attachment| - mail.attachments[attachment.filename] = { - :content_type => attachment.preferences['Content-Type'], - :mime_type => attachment.preferences['Mime-Type'], - :content => attachment.store_file.data - } - end - end - + mail = build(attr, notification) mail.delivery_method :smtp, { :openssl_verify_mode => 'none', :address => channel[:options][:host], @@ -53,6 +14,5 @@ class Channel::SMTP :enable_starttls_auto => true } mail.deliver - end end \ No newline at end of file