note description: "[ Component responsible to send email using an external mailer i.e: an external tool such as sendmail or a script, ... ]" date: "$Date$" revision: "$Revision$" class NOTIFICATION_EXTERNAL_MAILER inherit NOTIFICATION_MAILER SHARED_EXECUTION_ENVIRONMENT export {NONE} all end create make feature {NONE} -- Initialization make (a_exe: READABLE_STRING_GENERAL; args: detachable ITERABLE [READABLE_STRING_GENERAL]) -- Initialize `Current'. do set_parameters (a_exe, args) end executable_path: PATH arguments: detachable ARRAYED_LIST [READABLE_STRING_GENERAL] stdin_mode_set: BOOLEAN -- Use `stdin' to pass email message, rather than using local file? stdin_termination_sequence: detachable READABLE_STRING_8 -- Termination sequence for the stdin mode --| If any, this tells the executable all the data has been provided --| For instance, using sendmail, you should have "%N.%N%N" feature -- Status is_available: BOOLEAN do Result := (create {RAW_FILE}.make_with_path (executable_path)).exists end feature -- Change set_parameters (cmd: READABLE_STRING_GENERAL; args: detachable ITERABLE [READABLE_STRING_GENERAL]) -- Set parameters `executable_path' and associated `arguments' local l_args: like arguments do create executable_path.make_from_string (cmd) if args = Void then arguments := Void else create l_args.make (5) across args as c loop l_args.force (c.item) end arguments := l_args end end set_stdin_mode (b: BOOLEAN; v: like stdin_termination_sequence) -- Set the `stdin_mode_set' value -- and provide optional termination sequence when stdin mode is selected. do stdin_mode_set := b stdin_termination_sequence := v end feature -- Basic operation process_email (a_email: NOTIFICATION_EMAIL) local l_factory: PROCESS_FACTORY args: like arguments p: detachable PROCESS retried: INTEGER do if retried = 0 then create l_factory if stdin_mode_set then p := l_factory.process_launcher (executable_path.name, arguments, Void) p.set_hidden (True) p.set_separate_console (False) p.redirect_input_to_stream p.launch if p.launched then p.put_string (a_email.message) if attached stdin_termination_sequence as v then p.put_string (v) end p.put_string ("%N") -- End Of Input file. end else if attached arguments as l_args then args := l_args.twin else if attached new_temporary_file (generator) as f then f.create_read_write f.put_string (a_email.message) f.close create args.make (1) args.force (f.path.name) end end p := l_factory.process_launcher (executable_path.name, args, Void) p.set_hidden (True) p.set_separate_console (False) p.launch end if p.launched and not p.has_exited then execution_environment.sleep (1_000) p.wait_for_exit if not p.has_exited then p.terminate if not p.has_exited then execution_environment.sleep (1_000) p.wait_for_exit end end end elseif retried = 1 then if p /= Void and then p.launched and then not p.has_exited then p.terminate if not p.has_exited then execution_environment.sleep (1_000) p.wait_for_exit end end end rescue retried := retried + 1 retry end feature {NONE} -- Implementation new_temporary_file (a_extension: detachable READABLE_STRING_8): RAW_FILE -- Create file with temporary name. -- With concurrent execution, noting ensures that {FILE_NAME}.make_temporary_name is unique -- So using `a_extension' may help local bn: STRING_32 fn: PATH s: STRING_32 f: detachable like new_temporary_file i: INTEGER do -- With concurrent execution, nothing ensures that {FILE_NAME}.make_temporary_name is unique -- So let's try to find from create bn.make_from_string_general ((create {FILE_NAME}.make_temporary_name).string) create s.make_empty until f /= Void or i > 1000 loop create fn.make_from_string (bn) s.make_empty if i > 0 then s.append_character ('-') s.append_integer (i) fn := fn.appended (s) end if a_extension /= Void then fn := fn.appended_with_extension (a_extension) end create f.make_with_path (fn) if f.exists then i := i + 1 f := Void end end if f = Void then Result := new_temporary_file (Void) else Result := f check not_temporary_file_exists: not Result.exists end check temporary_creatable: Result.is_creatable end end ensure not_result_exists: not Result.exists result_creatable: Result.is_creatable end note copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end