File Coverage

blib/lib/Email/Sender/Server/Controller.pm
Criterion Covered Total %
statement 15 171 8.7
branch 0 58 0.0
condition 0 41 0.0
subroutine 5 21 23.8
pod 0 1 0.0
total 20 292 6.8


line stmt bran cond sub pod time code
1             package Email::Sender::Server::Controller;
2              
3 1     1   3579 use Moo;
  1         27268  
  1         7  
4 1     1   5863 use utf8;
  1         23  
  1         7  
5              
6 1     1   934 use Email::Sender::Server::Client;
  1         3  
  1         56  
7 1     1   6 use Email::Sender::Server::Manager;
  1         2  
  1         21  
8 1     1   7 use File::Copy;
  1         2  
  1         4696  
9              
10             our $VERSION = '1.000001'; # VERSION
11              
12             has arguments => (
13             is => 'rw',
14             lazy => 1,
15             builder => 1
16             );
17              
18             sub _build_arguments {[
19             # command-line arguments
20 0     0     ]}
21              
22             has commands => (
23             is => 'ro',
24             lazy => 1,
25             builder => 1
26             );
27              
28             sub _build_commands {{
29             # command-line commands
30 0     0     copy => {
31             abstract => 'copy the ess executable',
32             routine => \&_command_copy,
33             usage => qq{
34              
35             command: copy
36              
37             valid arguments are:
38              
39             ess copy to:"..." copies and renames the executable
40              
41             args syntax is :x for boolean and x:y for key/value
42              
43             }
44             },
45             clean => {
46             abstract => 'cleanup the file system',
47             routine => \&_command_clean,
48             usage => qq{
49              
50             command: clean
51              
52             args syntax is :x for boolean and x:y for key/value
53              
54             }
55             },
56             config => {
57             abstract => 'generate a config file',
58             routine => \&_command_config,
59             usage => qq{
60              
61             command: config
62              
63             args syntax is :x for boolean and x:y for key/value
64              
65             }
66             },
67             email => {
68             abstract => 'send an email real quick',
69             routine => \&_command_email,
70             usage => qq{
71              
72             command: email
73              
74             valid arguments are:
75              
76             ess email :text reads text from stdin
77             ess email :html reads text from stdin
78              
79             ess email text:"..." set email body text
80             ess email html:"..." set email body html
81              
82             ess email to:me\@abc.co from:you\@abc.co subject:test
83              
84             args syntax is :x for boolean and x:y for key/value
85              
86             }
87             },
88             help => {
89             abstract => 'display usage information',
90             routine => \&_command_help,
91             hidden => 1
92             },
93             start => {
94             abstract => 'start processing the email queue',
95             routine => \&_command_start,
96             usage => qq{
97              
98             command: start
99              
100             valid arguments are:
101              
102             ess start :w starts ess with 1 worker
103             ess start w:5 starts ess with 5 workers
104             ess start workers:1 starts ess with 1 worker
105              
106             args syntax is :x for boolean and x:y for key/value
107              
108             }
109             },
110             start_background => {
111             abstract => 'process the email queue in the background',
112             routine => \&_command_start_background,
113             hidden => 1
114             },
115             status => {
116             abstract => 'display ess processing information',
117             routine => \&_command_status,
118             usage => qq{
119              
120             command: status
121              
122             args syntax is :x for boolean and x:y for key/value
123              
124             }
125             },
126             stop => {
127             abstract => 'stop processing the email queue',
128             routine => \&_command_stop,
129             usage => qq{
130              
131             command: stop
132              
133             args syntax is :x for boolean and x:y for key/value
134              
135             }
136             },
137             testmail => {
138             abstract => 'send emails as a test',
139             routine => \&_command_testmail,
140             usage => qq{
141              
142             command: test
143              
144             valid arguments are:
145              
146             ess testmail i:15 send 15 test messages
147              
148             ess testmail :text reads text from stdin
149             ess testmail :html reads text from stdin
150              
151             ess testmail text:"..." set email body text
152             ess testmail html:"..." set email body html
153              
154             ess testmail to:me\@abc.co from:you\@abc.co subject:test
155              
156             args syntax is :x for boolean and x:y for key/value
157              
158             }
159             },
160             version => {
161             abstract => 'display version information',
162             routine => \&_command_version,
163             usage => qq{
164              
165             command: version
166              
167             args syntax is :x for boolean and x:y for key/value
168              
169             }
170             },
171             }};
172              
173             has command => (
174             is => 'rw',
175             required => 1
176             );
177              
178             sub execute_command {
179 0     0 0   my ($self, @args) = @_;
180 0           my ($options, $sequence) = $self->_parse_arguments(@args);
181              
182             # execute the command
183              
184 0           my $command = $self->command;
185 0           my @params = ($self, $options, $sequence);
186              
187 0 0         die "please use a valid command" unless $self->commands->{$command};
188              
189 0           my $output = $self->commands->{$command}->{routine}->(@params);
190              
191 0 0         unless ($output) {
192 0           $output = "\nError while executing $0 command ($command):\n\n";
193             }
194              
195 0           $output =~ s/^[ ]+//gm;
196 0           $output =~ s/^\n +/\n/gm;
197 0           $output =~ s/^\n{2,}/\n/gm;
198 0           $output =~ s/\n+$/\n/;
199              
200 0           print $output, "\n";
201             }
202              
203             sub _command_copy {
204 0     0     my ($self, $opts) = @_;
205              
206 0   0       my $to = $opts->{to} ||= 'new_ess';
207              
208 0           my $manager = Email::Sender::Server::Manager->new;
209              
210 0           File::Copy::copy($0, $manager->filepath('..', $to));
211 0           File::Copy::move($manager->directory, $manager->directory('..', "$to\_data"));
212              
213 0           chmod 0755, $manager->filepath('..', $to);
214              
215 0           rmdir $manager->directory;
216              
217 0           exit print "ESS Executable Copied Successfully\n";
218             }
219              
220             sub _command_clean {
221 0     0     my ($self, $opts) = @_;
222              
223 0           system $0, "stop" ;
224              
225 0           my $manager = Email::Sender::Server::Manager->new;
226              
227 0           $manager->cleanup;
228              
229 0           exit print "ESS Cleanup, Repair and Recovery Completed\n";
230             }
231              
232             sub _command_config {
233 0     0     my ($self, $opts) = @_;
234              
235 0           my $manager = Email::Sender::Server::Manager->new;
236              
237 0           $manager->create_config;
238              
239 0           exit print "ESS Config File Generated To Override Defaults\n";
240             }
241              
242             sub _command_email {
243 0     0     my ($self, $opts) = @_;
244              
245 0           my $client = Email::Sender::Server::Client->new;
246              
247             # capture message body from stdin
248              
249 0   0       $opts->{text} ||= '';
250 0   0       $opts->{html} ||= '';
251              
252 0 0 0       if ($opts->{text} eq '1' xor $opts->{html} eq '1') {
253 0           my @content = ();
254              
255 0 0         if (@content) {
256 0 0         if ($opts->{text}) {
257 0           $opts->{type} = 'text';
258 0           $opts->{message} = join "", @content;
259             }
260              
261 0 0         if ($opts->{html}) {
262 0           $opts->{type} = 'html';
263 0           $opts->{message} = join "", @content;
264             }
265             }
266             }
267              
268 0           delete $opts->{text};
269 0           delete $opts->{html};
270              
271 0           my $path = $client->email(%{$opts});
  0            
272              
273 0           exit print "Submitted Email for Processing (path: $path)\n";
274             }
275              
276             sub _command_help {
277 0     0     my ($self, $opts, $args) = @_;
278              
279 0           my $commands_string ;
280              
281 0 0         if ($args->[0]) {
282 0           my $command = $args->[0];
283              
284 0 0         if ($self->commands->{$command}) {
285 0 0         $commands_string = $self->commands->{$command}->{usage}
286             if $self->commands->{$command}->{usage};
287             }
288             }
289              
290 0 0         unless ($commands_string) {
291 0           my @commands = keys %{$self->commands};
  0            
292 0           my @ordered = sort { $a cmp $b } @commands;
  0            
293              
294 0           my ($max_chars) = length((
295              
296 0           sort { length($b) <=> length($a) }
297 0           grep { not defined $self->commands->{$_}->{hidden} } @commands
298              
299             )[0]);
300              
301 0           foreach my $name (@ordered) {
302 0 0         if (defined $self->commands->{$name}->{hidden}) {
303 0           next;
304             }
305              
306 0   0       my $desc = $self->commands->{$name}->{abstract}
307             || 'This Command has no Description';
308              
309 0           $commands_string .=
310             "\t$name" . (" " x ($max_chars - length($name))) . "\t $desc\n";
311             }
312             }
313              
314 0           return qq{
315              
316             usage: $0 COMMAND [ARGS]
317              
318             The command(s) info is as follows:
319              
320             $commands_string
321              
322             See '$0 help COMMAND' for more information on a specific command.
323              
324             }
325             }
326              
327             sub _command_start {
328 0     0     my ($self, $opts) = @_;
329              
330 0           my $pid = fork;
331              
332 0 0         $opts->{workers} = delete $opts->{w} if $opts->{w};
333              
334 0   0       $opts->{workers} ||= 3;
335              
336 0 0         exec $0, "start_background", "w:$opts->{workers}" unless $pid ;
337              
338 0           exit print "Starting ESS Background Process (pid: $$)\n";
339             }
340              
341             sub _command_start_background {
342 0     0     my ($self, $opts) = @_;
343              
344 0 0         $opts->{workers} = delete $opts->{w} if $opts->{w};
345              
346 0   0       $opts->{workers} ||= 3;
347              
348 0           my $manager = Email::Sender::Server::Manager->new(spawn => $opts->{workers});
349              
350 0           $manager->delegate_workload;
351             }
352              
353             sub _command_status {
354 0     0     my ($self, $opts) = @_;
355              
356 0           my $manager = Email::Sender::Server::Manager->new;
357              
358 0   0       my $queued_count = @{ $manager->message_filelist } || 0;
359              
360 0           print "ESS Qeueue has $queued_count Message(s)\n";
361              
362 0           opendir my $workspace_hdl, $manager->directory('worker');
363              
364 0           my @workers = grep { !/^\./ } readdir $workspace_hdl;
  0            
365              
366 0 0         if (@workers) {
367 0           print "ESS Currently Employs ".@workers." Worker(s)\n\n";
368              
369 0           foreach my $worker (@workers) {
370 0   0       my $count = @{ $manager->message_filelist('worker', $worker) } || 0;
371              
372 0           print "\tESS Worker $worker is Processing $count Message(s)\n";
373             }
374              
375 0           print "\n";
376             }
377              
378 0           my $passed_count = _count_files_in_directory(
379             $manager->directory('passed')
380             );
381              
382 0           my $failed_count = _count_files_in_directory(
383             $manager->directory('failed')
384             );
385              
386 0           print "ESS has successfully processed $passed_count Message(s)\n";
387 0           print "ESS has failed to process $failed_count Message(s)\n";
388              
389 0           exit ;
390             }
391              
392             sub _command_stop {
393 0     0     my ($self, $opts) = @_;
394              
395 0           my $manager = Email::Sender::Server::Manager->new;
396 0           my $flag_file = $manager->filepath('shutdown');
397              
398 0           open my $fh, ">", $flag_file;
399              
400 0           exit print "ESS Processing Shutdown Sequence Initiated\n";
401             }
402              
403             sub _command_testmail {
404 0     0     my ($self, $opts) = @_;
405              
406 0   0       $opts->{text} ||= '';
407 0   0       $opts->{html} ||= '';
408              
409 0 0 0       if ($opts->{text} eq '1' xor $opts->{html} eq '1') {
410 0           my @content = ();
411              
412 0 0         if (@content) {
413 0 0         if ($opts->{text}) {
414 0           $opts->{text} = join "", @content;
415             }
416              
417 0 0         if ($opts->{html}) {
418 0           $opts->{html} = join "", @content;
419             }
420             }
421             }
422              
423 0 0 0       $opts->{text} = <<'TEST' unless $opts->{text} || $opts->{html};
424              
425             # text
426             The quick brown fox jumps over the ......
427              
428             # random lorem
429             Lorem ipsum dolor sit amet, esse modus mundi id usu, dicit ....
430              
431             # random l33t
432             1T y0ur kl1k c4n, be r35u|7z n0n-3N9l1sh c@N, t3H 1T 1n70 250m p1cz!
433              
434             # random chinese
435             富士は日本一の山
436              
437             TEST
438              
439 0   0       my $i = $opts->{i} || 1;
440 0           my $x = 1;
441              
442 0           for (1..$i) {
443              
444             # pause per 10 submissions in an attempt to not overwhelm the system
445 0 0 0       $x = 0 && sleep 5 if $i > $_ && $x == 10;
446              
447 0           my $client = Email::Sender::Server::Client->new;
448              
449 0   0       my @message = (
450             to => $opts->{to},
451             from => $opts->{from},
452             subject => $opts->{subject} || "ESS Test Msg: #".$_,
453             );
454              
455 0 0         push @message, (type => 'text', message => $opts->{text})
456             if $opts->{text};
457              
458 0 0         push @message, (type => 'html', message => $opts->{html})
459             if $opts->{html};
460              
461 0           my $path = $client->email({@message});
462              
463 0 0         $path ?
464             print "Processed email to: $message[1] - $path\n" :
465             print "Failed processing email to: $message[1]\n" ;
466              
467             }
468              
469 0           exit print "ESS has processed $i test messages (hope everything is OK)\n";
470             }
471              
472             sub _command_version {
473 0     0     my ($self, $opts) = @_;
474              
475 0           my $version = do {
476 0           my $name = "Email-Sender-Server (ESS)";
477 0           my $version = '0.00';
478              
479 0           eval { $version = $Email::Sender::Server::Manager::VERSION } ;
  0            
480 0   0       join " ", $name, $version || '0.00'
481             };
482              
483 0           exit print "$version\n";
484             }
485              
486             sub _count_files_in_directory {
487 0     0     my ($directory) = @_;
488              
489 0           my @files = (glob "$directory/*.msg");
490 0           my $count = scalar @files;
491              
492 0 0         my @sub_directories = grep {
493 0           -d $_ && $_ !~ /\.+$/
494             } glob "$directory/*";
495              
496 0           for my $directory (@sub_directories) {
497 0           $count += _count_files_in_directory($directory);
498             }
499              
500 0           return $count;
501             }
502              
503             sub _parse_arguments {
504 0     0     my ($self, @args) = @_;
505              
506 0 0         @args = @{$self->arguments} unless @args;
  0            
507              
508 0           my $params = {};
509 0           my $sequence = [];
510              
511 0           for (my $i=0; $i<@args; $i++) {
512 0           my $arg = $args[$i];
513              
514 0 0         if ($arg =~ /^:(.*)/) {
    0          
    0          
515 0           $params->{$1} = 1;
516             }
517             elsif ($arg =~ /(.*):$/) {
518 0           $params->{$1} = $args[++$i];
519             }
520             elsif ($arg =~ /([^:]+):(.*)$/) {
521 0           $params->{$1} = $2;
522             }
523             else {
524 0           push @{$sequence}, $arg;
  0            
525             }
526             }
527              
528 0           return ($params, $sequence);
529             }
530              
531             1;