ArticleSend via SOAP (Perl) Encoding Problem

Moderator: crythias

Locked
iamhavoc
Znuny newbie
Posts: 6
Joined: 05 Feb 2013, 19:34
Znuny Version: 3.1.12
Real Name: Fabian

ArticleSend via SOAP (Perl) Encoding Problem

Post by iamhavoc »

Hi,

I'm currently trying to create and send articles via the SOAP interface with perl. I'm running into problems when submitting the article. Either 'text/plain' or 'text/html' body submitted via SOAP::Lite will be encoded (<>& etc), transmitted but not decoded on the OTRS server side. I'm having charset UTF-8 in the ArticleSend method as well as in OTRS itself and the database. When I'm submitting "PLAINTEXT<>&" it will be received and saved as "PLAINTEXT<>&" which is definitely a problem and I did not yet find a solution so I hope you'll be able to help.

I'm attaching the code (the client-library at least) here. Input comes from a MIME::Entity mail object which will be parsed for the necessary data for OTRS.

Code: Select all

#!/usr/bin/perl

package OTRS::Client;

use strict;
use warnings;

use SOAP::Lite;
use Data::Dumper;
use MIME::Entity;
use Encode;
use HTML::Entities;

use constant DEFAULT_SENDER_TYPE 		=> 'system';
use constant DEFAULT_ARTICLE_TYPE 		=> 'email-external';
use constant DEFAULT_LOCK_TYPE			=> 'unlock';
use constant DEFAULT_STATE				=> 'closed successful';
use constant DEFAULT_QUEUE				=> 'Raw';
use constant DEFAULT_OWNER_ID			=> 1;
use constant DEFAULT_USER_ID			=> 1;
use constant DEFAULT_PRIORITY			=> "3 normal";

my $RPC;

sub new {
	my $class = shift;
	my %data = @_;

    my $self = {
        _proxy => $data{proxy},
        _uri => $data{uri},
    	_username => $data{username},
    	_password => $data{password},
    };

    print "Class: ".$class."\n";
    print "Proxy: ".$self->{_proxy}."\n";
    print "URI: ".$self->{_uri}."\n";
    print "Username: ".$self->{_username}."\n";
    print "Password: ".$self->{_password}."\n";

    bless $self, $class;

    # Create OTRS Soap Object
    $RPC = new SOAP::Lite( encoding => 'utf-8', proxy => $self->{_proxy}, uri => $self->{_uri} );
    return $self;
}

sub sendMail {
	# Expects 1 Paramenter: MIME Entity

	if (my ( $self, $mail ) = @_) {
		# Get the mail head
		my $head = $mail->head;

		my %HEADER;
		
		# Gather HEAD-Fields needed for OTRS
		$HEADER{'From'} = $head->get('From');
		$HEADER{'To'} = $head->get('To');
		$HEADER{'Subject'} = $head->get('Subject');
		$HEADER{'Content-Type'} = $head->get('Content-Type');

		$HEADER{'Cc'} = $head->get('Cc')
			if ($head->get('Cc'));

		$HEADER{'ReplyTo'} = $head->get('Reply-To')
			if ($head->get('Reply-To'));

		# Check for OTRS X- Attributes
		# ----------------------------
		# X-OTRS-Type 						default
		# X-OTRS-Service					-
		# X-OTRS-SLA						-
		# X-OTRS-ArticleKey(1|2|3)
		# X-OTRS-ArticleValue(1|2|3)
		# X-OTRS-TicketKey(1|2|...|8)
		# X-OTRS-TicketValue(1|2|...|8)
		# X-OTRS-Loop						True (Default: true)

		my %OTRS_TICKET_FLAGS;
		my %OTRS_ARTICLE_FLAGS;

		# X-OTRS-Priority 					1 very low, 2 low, 3 normal, 4 high, 5 very high
		$OTRS_TICKET_FLAGS{'Priority'} = ($head->get('X-OTRS-Priority')) ? $head->get('X-OTRS-Priority') : DEFAULT_PRIORITY;

		# X-OTRS-Queue						Queue-Name
		$OTRS_TICKET_FLAGS{'Queue'} = ($head->get('X-OTRS-Queue')) ? $head->get('X-OTRS-Queue') : DEFAULT_QUEUE;

		# X-OTRS-Lock						lock,unlock
		$OTRS_TICKET_FLAGS{'Lock'} = ($head->get('X-OTRS-Lock')) ? $head->get('X-OTRS-Lock') : DEFAULT_LOCK_TYPE;

		# X-OTRS-State 						new, open, closed successful, closed unsuccessful, ...
		$OTRS_TICKET_FLAGS{'State'} = ($head->get('X-OTRS-State')) ? $head->get('X-OTRS-State') : DEFAULT_STATE;

		# X-OTRS-State-PendingTime			2010-11-20 00:00:00
		$OTRS_TICKET_FLAGS{'State-PendingTime'} = $head->get('X-OTRS-State-PendingTime')
			if ($head->get('X-OTRS-State-PendingTime'));

		# X-OTRS-CustomerUser				CustomerUser
		$OTRS_TICKET_FLAGS{'CustomerUser'} = $head->get('X-OTRS-CustomerUser')
			if ($head->get('X-OTRS-CustomerUser'));

		# X-OTRS-CustomerNo					CustomerNo
		$OTRS_TICKET_FLAGS{'CustomerNo'} = $head->get('X-OTRS-CustomerNo')
			if ($head->get('X-OTRS-CustomerNo'));

		# X-OTRS-SenderType					agent, system, customer
		$OTRS_ARTICLE_FLAGS{'SenderType'} = ($head->get('X-OTRS-SenderType')) ? $head->get('X-OTRS-SenderType') : DEFAULT_SENDER_TYPE;

		# X-OTRS-ArticleType				email-external, email-internal, email-notification-ext, email-notification-int, phone, fax, sms, webrequest, note-internal, note-external, note-report
		$OTRS_ARTICLE_FLAGS{'ArticleType'} = ($head->get('X-OTRS-ArticleType')) ? $head->get('X-OTRS-ArticleType') : DEFAULT_ARTICLE_TYPE;

		# Create Ticketnumber
		my $SOM = $RPC->Dispatch( $self->{_username}, $self->{_password}, 'TicketObject', 'TicketCreateNumber' );
		die $SOM->fault()->{faultstring} if $SOM->fault();

		my $TicketNumber = $SOM->result();

		if ($TicketNumber) {
			# Create Ticket
			my %TicketData = (
			    TN           => $TicketNumber,
			    Title        => $HEADER{'Subject'},
			    OwnerID		 =>	DEFAULT_OWNER_ID,
			    UserID		 =>	DEFAULT_USER_ID
			);

			%TicketData = (%TicketData,%OTRS_TICKET_FLAGS);

			$SOM = $RPC->Dispatch( $self->{_username}, $self->{_password}, 'TicketObject', 'TicketCreate', %TicketData => 1 );
			die $SOM->fault()->{faultstring} if $SOM->fault();
			my $TicketID = $SOM->result();

			# Ticket Created successfully
			if ($TicketID) {
				# Get Mail Body
				# my $body = $mail->body;
				my $body;
				my $attachment;
				my @attachments = ();
				my $content_mime_type;

				if ($mail->parts > 0) {
					for (my $i=0;$i<$mail->parts;$i++) {
						my $subEntity = $mail->parts($i);
						print ">> MIME: ", $subEntity->mime_type," \n";

						my $mime_type = $subEntity->mime_type;
						#if ($mime_type eq 'text/plain') {
							# if (my $io = $subEntity->open("r")) {
					  #           while (defined($_=$io->getline)) {
					  #           	#print $_;
					  #           	#$body = $body.$_;
					  #           	$body = join "",  @{$subEntity->body};
					  #           	next;
					  #           }
					  #           $io->close;
					  #       }
					  # 		$attachment = {
							# 	Content => $subEntity->bodyhandle->as_string,
							# 	ContentType => $mime_type,
							# 	MimeType => $mime_type
							# };

							# push (@attachments, $attachment);
						#}
						if ($mime_type eq 'text/html' || $mime_type eq 'text/plain') {
							my $plainbody = $subEntity->stringify_body;
							$body = $body.$plainbody;
							$content_mime_type = $mime_type;

							print Dumper($body);
						}
						else {
							# It's any form of attachment
							print "Filename: ".$subEntity->head->mime_attr('content-disposition.filename');
							$attachment = {
								Content => $subEntity->bodyhandle->as_string,
								ContentType => $mime_type,
								Filename => $subEntity->head->mime_attr('content-disposition.filename')
							};

							push (@attachments, $attachment);
						}
					}
				}
				else {
					my $content_mime_type = $mail->mime_type;
				    $body = join "",  @{$mail->body};
				}

				print Dumper($body);
				print "MIME TYPE BEFORE ARRAY: ".$content_mime_type;
				my %ArticleData = (
				    TicketID         => $TicketID,
				 	From             => $HEADER{'From'},
				    To               => $HEADER{'To'},
				    Cc               => $HEADER{'Cc'},
				    ReplyTo          => $HEADER{'ReplyTo'},
				    Subject          => $HEADER{'Subject'},
				    #ContentType      => $content_mime_type,
				    MimeType         => $content_mime_type,
				    #MimeType         => $HEADER{'Content-Type'},
				    UserID         	 => DEFAULT_USER_ID,
				    Body             => $body,
				    Charset          => 'utf-8',
				    HistoryType      => 'EmailCustomer',
				    HistoryComment   => 'Created by OTRS::Client Module',
				    NoAgentNotify    => 0, 
				    Loop             => 0,
				    Attachment 		 => \@attachments,
				);

				# Merge Arg Arrays
				%ArticleData = (%ArticleData,%OTRS_ARTICLE_FLAGS);

				$SOM = $RPC->Dispatch($self->{_username}, $self->{_password}, 'TicketObject', 'ArticleSend', %ArticleData => 1 );
				die $SOM->fault()->{faultstring} if $SOM->fault();
				my $ArticleID = $SOM->result();
				print "NOTICE: ArticleID is $ArticleID\n";
			}
		}

		return 1;
	}

	die;
	
}
1;
A possible client call could look as follows:

Code: Select all

my $client = new OTRS::Client(
    proxy => "http://OTRSURL/otrs/rpc.pl",
    uri => "http://localhost/Core",
    username => "USER",
    password => "PASS"
);

my $content = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html"/></head><body><h1><Hallo Welt</h1><p>TEST</p></body></html>';
my $content_plain = "PLAIN PLAIN PLAIN PLAIN<>&";

my $mail = MIME::Entity->build(
    Type    =>"multipart/alternative",
    From    => "test\@example.net",
    To      => "test1\@example.net",
    Subject => "OTRS Perl Bridge TESTMAIL"
);

# $mail->attach(Path => "/usr/local/bin/pic1.jpg",
#          Type        => "image/jpeg",
#          Encoding    => "base64");

# $mail->attach(Path => "/usr/local/bin/pic2.gif",
#          Type        => "image/gif",
#          Encoding    => "base64");

$mail->attach(  Data=>$content,
              Type=>"text/html");

#$mail->attach(  Data=>$content_plain,
#               Type=>"text/plain");

$client->sendMail($mail);
As mentioned, the BODY part will be encoded as soon as it's transmitted via SOAP and then not decoded on the OTRS side. I hope you'll be able to help :)
iamhavoc
Znuny newbie
Posts: 6
Joined: 05 Feb 2013, 19:34
Znuny Version: 3.1.12
Real Name: Fabian

Re: ArticleSend via SOAP (Perl) Encoding Problem

Post by iamhavoc »

Fixed, was an error in my test-installation.
Locked