Added email channel backend validation.
This commit is contained in:
parent
8c8788b0cc
commit
27081708b1
9 changed files with 176 additions and 238 deletions
|
@ -5,198 +5,6 @@ class ChannelsController < ApplicationController
|
|||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
GET /api/v1/channels/#{id}.json
|
||||
|
||||
Response example 1:
|
||||
|
||||
{
|
||||
"id":1,
|
||||
"area":"Email::Account",
|
||||
"group_id:": 1,
|
||||
"options":{
|
||||
"inbound": {
|
||||
"adapter":"IMAP",
|
||||
"options": {
|
||||
"host":"mail.example.com",
|
||||
"user":"some_user",
|
||||
"password":"some_password",
|
||||
"ssl":true
|
||||
},
|
||||
"outbound":{
|
||||
"adapter":"SMTP",
|
||||
"options": {
|
||||
"host":"mail.example.com",
|
||||
"user":"some_user",
|
||||
"password":"some_password",
|
||||
"start_tls":true
|
||||
}
|
||||
},
|
||||
"active":true,
|
||||
"updated_at":"2012-09-14T17:51:53Z",
|
||||
"created_at":"2012-09-14T17:51:53Z",
|
||||
"updated_by_id":2.
|
||||
"created_by_id":2,
|
||||
}
|
||||
|
||||
Response example 2:
|
||||
|
||||
{
|
||||
"id":1,
|
||||
"area":"Twitter::Account",
|
||||
"group_id:": 1,
|
||||
"options":{
|
||||
"adapter":"Twitter",
|
||||
"auth": {
|
||||
"consumer_key":"PJ4c3dYYRtSZZZdOKo8ow",
|
||||
"consumer_secret":"ggAdnJE2Al1Vv0cwwvX5bdvKOieFs0vjCIh5M8Dxk",
|
||||
"oauth_token":"293437546-xxRa9g74CercnU5AvY1uQwLLGIYrV1ezYtpX8oKW",
|
||||
"oauth_token_secret":"ju0E4l9OdY2Lh1iTKMymAu6XVfOaU2oGxmcbIMRZQK4",
|
||||
},
|
||||
"sync":{
|
||||
"search":[
|
||||
{
|
||||
"term":"#otrs",
|
||||
"type": "mixed", # optional, possible 'mixed' (default), 'recent', 'popular'
|
||||
"group_id:": 1,
|
||||
"limit": 1, # optional
|
||||
},
|
||||
{
|
||||
"term":"#zombie23",
|
||||
"group_id:": 2,
|
||||
},
|
||||
{
|
||||
"term":"#otterhub",
|
||||
"group_id:": 3,
|
||||
}
|
||||
],
|
||||
"mentions" {
|
||||
"group_id:": 4,
|
||||
"limit": 100, # optional
|
||||
},
|
||||
"direct_messages": {
|
||||
"group_id:": 4,
|
||||
"limit": 1, # optional
|
||||
}
|
||||
}
|
||||
},
|
||||
"active":true,
|
||||
"updated_at":"2012-09-14T17:51:53Z",
|
||||
"created_at":"2012-09-14T17:51:53Z",
|
||||
"updated_by_id":2.
|
||||
"created_by_id":2,
|
||||
}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/channels/#{id}.json -v -u #{login}:#{password}
|
||||
|
||||
=end
|
||||
|
||||
def show
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
return if !check_access
|
||||
model_show_render(Channel, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
POST /api/v1/channels.json
|
||||
|
||||
Payload:
|
||||
{
|
||||
"area":"Email::Account",
|
||||
"group_id:": 1,
|
||||
"options":{
|
||||
"inbound":
|
||||
"adapter":"IMAP",
|
||||
"options":{
|
||||
"host":"mail.example.com",
|
||||
"user":"some_user",
|
||||
"password":"some_password",
|
||||
"ssl":true
|
||||
},
|
||||
},
|
||||
"outbound":{
|
||||
"adapter":"SMTP",
|
||||
"options": {
|
||||
"host":"mail.example.com",
|
||||
"user":"some_user",
|
||||
"password":"some_password",
|
||||
"start_tls":true
|
||||
}
|
||||
},
|
||||
"active":true,
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"area":"Email::Account",
|
||||
...
|
||||
}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||
|
||||
=end
|
||||
|
||||
def create
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_create_render(Channel, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
PUT /api/v1/channels/{id}.json
|
||||
|
||||
Payload:
|
||||
{
|
||||
"id":1,
|
||||
"area":"Email::Account",
|
||||
"group_id:": 1,
|
||||
"options":{
|
||||
"inbound":
|
||||
"adapter":"IMAP",
|
||||
"options":{
|
||||
"host":"mail.example.com",
|
||||
"user":"some_user",
|
||||
"password":"some_password",
|
||||
"ssl":true
|
||||
},
|
||||
},
|
||||
"outbound":{
|
||||
"adapter":"SMTP",
|
||||
"options": {
|
||||
"host":"mail.example.com",
|
||||
"user":"some_user",
|
||||
"password":"some_password",
|
||||
"start_tls":true
|
||||
}
|
||||
},
|
||||
"active":true,
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": 1,
|
||||
"name": "some_name",
|
||||
...
|
||||
}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||
|
||||
=end
|
||||
|
||||
def update
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
return if !check_access
|
||||
model_update_render(Channel, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
DELETE /api/v1/channels/{id}.json
|
||||
|
||||
|
@ -405,15 +213,6 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten
|
|||
|
||||
adapter = params[:adapter].downcase
|
||||
|
||||
# validate adapter
|
||||
if adapter !~ /^(smtp|sendmail)$/
|
||||
render json: {
|
||||
result: 'failed',
|
||||
message: "Unknown adapter '#{adapter}'",
|
||||
}
|
||||
return
|
||||
end
|
||||
|
||||
email = Setting.get('notification_sender')
|
||||
|
||||
# connection test
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Channel < ApplicationModel
|
||||
load 'channel/assets.rb'
|
||||
include Channel::Assets
|
||||
|
||||
store :options
|
||||
store :preferences
|
||||
|
||||
|
@ -34,9 +37,7 @@ fetch one account
|
|||
|
||||
adapter = options[:adapter]
|
||||
adapter_options = options
|
||||
if options[:options]
|
||||
adapter_options = options[:options]
|
||||
elsif options[:inbound] && options[:inbound][:adapter]
|
||||
if options[:inbound] && options[:inbound][:adapter]
|
||||
adapter = options[:inbound][:adapter]
|
||||
adapter_options = options[:inbound][:options]
|
||||
end
|
||||
|
@ -79,9 +80,7 @@ send via account
|
|||
|
||||
adapter = options[:adapter]
|
||||
adapter_options = options
|
||||
if options[:options]
|
||||
adapter_options = options[:options]
|
||||
elsif options[:outbound] && options[:outbound][:adapter]
|
||||
if options[:outbound] && options[:outbound][:adapter]
|
||||
adapter = options[:outbound][:adapter]
|
||||
adapter_options = options[:outbound][:options]
|
||||
end
|
||||
|
|
54
app/models/channel/assets.rb
Normal file
54
app/models/channel/assets.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Channel
|
||||
module Assets
|
||||
|
||||
=begin
|
||||
|
||||
get all assets / related models for this channel
|
||||
|
||||
channel = Channel.find(123)
|
||||
result = channel.assets( assets_if_exists )
|
||||
|
||||
returns
|
||||
|
||||
result = {
|
||||
:channels => {
|
||||
123 => channel_model_123,
|
||||
1234 => channel_model_1234,
|
||||
}
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def assets (data = {})
|
||||
|
||||
if !data[ self.class.to_app_model ]
|
||||
data[ self.class.to_app_model ] = {}
|
||||
end
|
||||
if !data[ self.class.to_app_model ][ id ]
|
||||
attributes = attributes_with_associations
|
||||
|
||||
# remove passwords
|
||||
%w(inbound outbound).each {|key|
|
||||
if attributes['options'] && attributes['options'][key] && attributes['options'][key]['options']
|
||||
attributes['options'][key]['options'].delete('password')
|
||||
end
|
||||
}
|
||||
|
||||
data[ self.class.to_app_model ][ id ] = attributes
|
||||
end
|
||||
|
||||
|
||||
return data if !self['created_by_id'] && !self['updated_by_id']
|
||||
%w(created_by_id updated_by_id).each {|local_user_id|
|
||||
next if !self[ local_user_id ]
|
||||
next if data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ]
|
||||
user = User.lookup( id: self[ local_user_id ] )
|
||||
data = user.assets( data )
|
||||
}
|
||||
data
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -1,20 +1,44 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Channel::Driver::Smtp
|
||||
|
||||
=begin
|
||||
|
||||
instance = Channel::Driver::Smtp.new
|
||||
instance.send(
|
||||
host: 'some.host',
|
||||
port: 25,
|
||||
enable_starttls_auto: true, # optional
|
||||
user: 'someuser',
|
||||
password: 'somepass'
|
||||
)
|
||||
|
||||
=end
|
||||
|
||||
def send(options, attr, notification = false)
|
||||
|
||||
# return if we run import mode
|
||||
return if Setting.get('import_mode')
|
||||
|
||||
# set smtp defaults
|
||||
if !options.key?(:port)
|
||||
options[:port] = 25
|
||||
end
|
||||
if !options.key?(:enable_starttls_auto)
|
||||
options[:enable_starttls_auto] = true
|
||||
end
|
||||
if !options.key?(:openssl_verify_mode)
|
||||
options[:openssl_verify_mode] = 'none'
|
||||
end
|
||||
mail = Channel::EmailBuild.build(attr, notification)
|
||||
mail.delivery_method :smtp, {
|
||||
openssl_verify_mode: 'none',
|
||||
openssl_verify_mode: options[:openssl_verify_mode],
|
||||
address: options[:host],
|
||||
port: options[:port] || 25,
|
||||
port: options[:port],
|
||||
domain: options[:host],
|
||||
user_name: options[:user],
|
||||
password: options[:password],
|
||||
enable_starttls_auto: true,
|
||||
enable_starttls_auto: options[:enable_starttls_auto],
|
||||
}
|
||||
mail.deliver
|
||||
end
|
||||
|
|
|
@ -10,9 +10,6 @@ Zammad::Application.routes.draw do
|
|||
match api_path + '/channels/email_notification', to: 'channels#email_notification', via: :post
|
||||
|
||||
# channels
|
||||
match api_path + '/channels/:id', to: 'channels#show', via: :get
|
||||
match api_path + '/channels', to: 'channels#create', via: :post
|
||||
match api_path + '/channels/:id', to: 'channels#update', via: :put
|
||||
match api_path + '/channels/:id', to: 'channels#destroy', via: :delete
|
||||
|
||||
end
|
||||
|
|
|
@ -2,6 +2,34 @@ module EmailHelper
|
|||
|
||||
=begin
|
||||
|
||||
get available driver
|
||||
|
||||
result = EmailHelper.available_driver
|
||||
|
||||
returns
|
||||
|
||||
{
|
||||
:inbound => ['imap', 'pop3'],
|
||||
:outbound => ['smtp', 'sendmail'],
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.available_driver
|
||||
if Setting.get('system_online_service')
|
||||
return {
|
||||
:inbound => ['imap', 'pop3'],
|
||||
:outbound => ['smtp'],
|
||||
}
|
||||
end
|
||||
{
|
||||
:inbound => ['imap', 'pop3'],
|
||||
:outbound => ['smtp', 'sendmail'],
|
||||
}
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
get mail parts
|
||||
|
||||
user, domain = EmailHelper.parse_email('somebody@example.com')
|
||||
|
|
|
@ -188,14 +188,17 @@ returns on fail
|
|||
|
||||
adapter = params[:adapter].downcase
|
||||
|
||||
# validate adapter
|
||||
if !EmailHelper.available_driver[:inbound].include?(adapter)
|
||||
return {
|
||||
result: 'failed',
|
||||
message: "Unknown adapter '#{adapter}'",
|
||||
}
|
||||
end
|
||||
|
||||
# connection test
|
||||
begin
|
||||
|
||||
# validate adapter
|
||||
if adapter !~ /^(imap|pop3)$/
|
||||
fail "Unknown adapter '#{adapter}'"
|
||||
end
|
||||
|
||||
require "channel/driver/#{adapter.to_filename}"
|
||||
|
||||
driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}")
|
||||
|
@ -264,6 +267,14 @@ returns on fail
|
|||
|
||||
adapter = params[:adapter].downcase
|
||||
|
||||
# validate adapter
|
||||
if !EmailHelper.available_driver[:outbound].include?(adapter)
|
||||
return {
|
||||
result: 'failed',
|
||||
message: "Unknown adapter '#{adapter}'",
|
||||
}
|
||||
end
|
||||
|
||||
# prepare test email
|
||||
if subject
|
||||
mail = {
|
||||
|
@ -288,21 +299,6 @@ returns on fail
|
|||
# test connection
|
||||
begin
|
||||
|
||||
# validate adapter
|
||||
if adapter !~ /^(smtp|sendmail)$/
|
||||
fail "Unknown adapter '#{adapter}'"
|
||||
end
|
||||
|
||||
# set smtp defaults
|
||||
if adapter =~ /^smtp$/
|
||||
if !params[:options].key?(:port)
|
||||
params[:options][:port] = 25
|
||||
end
|
||||
if !params[:options].key?(:ssl)
|
||||
params[:options][:ssl] = true
|
||||
end
|
||||
end
|
||||
|
||||
require "channel/driver/#{adapter.to_filename}"
|
||||
|
||||
driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}")
|
||||
|
|
|
@ -67,6 +67,16 @@ or
|
|||
return result
|
||||
end
|
||||
|
||||
# validate adapter
|
||||
adapter = params[:inbound][:adapter].downcase
|
||||
if !EmailHelper.available_driver[:inbound].include?(adapter)
|
||||
return {
|
||||
result: 'failed',
|
||||
message: "Unknown adapter '#{adapter}'",
|
||||
}
|
||||
return
|
||||
end
|
||||
|
||||
# looking for verify email
|
||||
(1..10).each {
|
||||
sleep 5
|
||||
|
@ -75,11 +85,11 @@ or
|
|||
found = nil
|
||||
|
||||
begin
|
||||
if params[:inbound][:adapter] =~ /^imap$/i
|
||||
found = Channel::Driver::Imap.new.fetch(params[:inbound][:options], self, 'verify', subject)
|
||||
else
|
||||
found = Channel::Driver::Pop3.new.fetch(params[:inbound][:options], self, 'verify', subject)
|
||||
end
|
||||
require "channel/driver/#{adapter.to_filename}"
|
||||
|
||||
driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}")
|
||||
driver_instance = driver_class.new
|
||||
found = driver_instance.fetch(params[:inbound][:options], self, 'verify', subject)
|
||||
rescue => e
|
||||
result = {
|
||||
result: 'invalid',
|
||||
|
|
|
@ -139,6 +139,20 @@ class EmailHelperTest < ActiveSupport::TestCase
|
|||
|
||||
test 'z probe_inbound' do
|
||||
|
||||
# invalid adapter
|
||||
result = EmailHelper::Probe.inbound(
|
||||
adapter: 'imap2',
|
||||
options: {
|
||||
host: 'not_existsing_host',
|
||||
port: 993,
|
||||
ssl: true,
|
||||
user: 'some@example.com',
|
||||
password: 'password',
|
||||
}
|
||||
)
|
||||
|
||||
assert_equal('failed', result[:result])
|
||||
|
||||
# network issues
|
||||
result = EmailHelper::Probe.inbound(
|
||||
adapter: 'imap',
|
||||
|
@ -256,6 +270,23 @@ class EmailHelperTest < ActiveSupport::TestCase
|
|||
|
||||
test 'z probe_outbound' do
|
||||
|
||||
# invalid adapter
|
||||
result = EmailHelper::Probe.outbound(
|
||||
{
|
||||
adapter: 'smtp2',
|
||||
options: {
|
||||
host: 'not_existsing_host',
|
||||
port: 25,
|
||||
start_tls: true,
|
||||
user: 'some@example.com',
|
||||
password: 'password',
|
||||
},
|
||||
},
|
||||
'some@example.com',
|
||||
)
|
||||
|
||||
assert_equal('failed', result[:result])
|
||||
|
||||
# network issues
|
||||
result = EmailHelper::Probe.outbound(
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue