Send email from Oracle 12c with postfix on Oracle Linux 7 - gmail

I have postfix service on my Oracle Linux and they work well done.
I use function
create or replace procedure Send_Mail(Msg_To varchar2, Msg_Subject varchar2, Msg_Text varchar2) is
c Utl_Smtp.Connection;
Rc integer;
Msg_From varchar2(50) := 'me#me.com'; -- email of my company which hosted on Gmail
Mailhost varchar2(30) := 'smtp.gmail.com';
begin
c := Utl_Smtp.Open_Connection(Mailhost, 587);
Utl_Smtp.Helo(c, Mailhost);
Utl_Smtp.StartTLS(c);
Utl_Smtp.Mail(c, Msg_From);
Utl_Smtp.Rcpt(c, Msg_To);
Utl_Smtp.Data(c,
'From: Oracle Database' || Utl_Tcp.Crlf || 'To: ' || Msg_To || Utl_Tcp.Crlf || 'Subject: ' || Msg_Subject || Utl_Tcp.Crlf ||
Msg_Text);
Utl_Smtp.Quit(c);
exception
when Utl_Smtp.Invalid_Operation then
Dbms_Output.Put_Line(' Invalid Operation in Mail attempt
using UTL_SMTP.');
when Utl_Smtp.Transient_Error then
Dbms_Output.Put_Line(' Temporary e-mail issue - try again');
when Utl_Smtp.Permanent_Error then
Dbms_Output.Put_Line(' Permanent Error Encountered.');
end;
which I found on http://www.dba-oracle.com/t_utl_smtp_utility.htm
when I run function
BEGIN
send_mail(msg_to => 'me#me.com',
msg_subject => 'Test subject',
msg_text => 'Test text');
END;
I get a error:
ORA-29279: SMTP permanent error: 530 5.7.0 Must issue a STARTTLS command first. im3sm2477330wjb.13 - gsmtp /* 132/5 selected symbols */
what I did wrong or what I must do?

The error is mentioned in the documentation, which also tells you how to secure the SMTP connection using SSL/TLS. You need to call utl_smtp.starttls().
...
begin
c := Utl_Smtp.Open_Connection(Mailhost, 587);
Utl_Smtp.Ehlo(c, Mailhost);
Utl_Smtp.StartTLS(c);
Utl_Smtp.Ehlo(c, Mailhost);
Utl_Smtp.Mail(c, Msg_From);
Utl_Smtp.Rcpt(c, Msg_To);
...

Related

ORACLE UTL_SMTP SMTP permanent error: 535 5.7.8

I'm trying to send email with Oracle APEX 20.1, hence, I've configured the wallet with gmail certificates as I've done before, but now every time I attempt to send an email, always get the same response from google smtp servers:
SMTP permanent error: 535 5.7.8 https://support.google.com/mail/?p=BadCredentials o40-20020a17090a0a2b00b001c77ebd8fa9sm275647pjo.17 - gsmtp
I've trippled check the account credentials, and the account security setting for untrusted apps is enabled.
Here's my procedure for sending email:
No 2 step verification is enabled.
At this point I'm really confused on what might been going on here.
create or replace PROCEDURE SEND_EMAIL(v_to varchar2, v_subject varchar2, v_mensaje varchar2) IS
c utl_smtp.connection;
l_mailhost VARCHAR2 (64) := 'smtp.gmail.com';
l_from VARCHAR2(64) := 'test#test.com';
l_from_alias VARCHAR2 (64) := 'testa#test.com';
l_to VARCHAR2 (64) := v_to;
l_subject VARCHAR2 (64) := v_subject;
l_conn utl_smtp.connection;
l_reply utl_smtp.reply;
crlf varchar2(2) := UTL_TCP.CRLF;
BEGIN
c := utl_smtp.open_connection(
host => l_mailhost,
port => 587,
wallet_path => 'file:/xxxxx/xxxxx',
wallet_password => 'xxxxxxxx',
secure_connection_before_smtp => false);
dbms_output.put_line('utl_smtp.open_connection');
--UTL_SMTP.EHLO(c, 'panamaensalarios.com');
UTL_SMTP.EHLO(c, 'smtp.gmail.com');
UTL_SMTP.starttls(c);
dbms_output.put_line('Usuario : '|| utl_raw.cast_to_varchar2( utl_encode.base64_encode( utl_raw.cast_to_raw(l_from))));
utl_smtp.command( c, 'AUTH LOGIN');
utl_smtp.command( c, utl_raw.cast_to_varchar2( utl_encode.base64_encode( utl_raw.cast_to_raw(l_from))));
utl_smtp.command( c, utl_raw.cast_to_varchar2( utl_encode.base64_encode( utl_raw.cast_to_raw([some_password]))));
UTL_SMTP.mail (c, l_from);
UTL_SMTP.rcpt (c, l_to);
UTL_SMTP.open_data (c);
UTL_SMTP.write_data (c, 'Date: ' || TO_CHAR (SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || crlf);
--UTL_SMTP.write_data (c, 'From: ' || l_from_alias || crlf);
UTL_SMTP.write_data (c, 'From: ' || l_from || crlf);
UTL_SMTP.write_data (c, 'Subject: ' || l_subject || crlf);
UTL_SMTP.write_data (c, 'To: ' || l_to || crlf);
UTL_SMTP.write_data (c, '' || crlf);
--FOR i IN 1 .. 10
-- LOOP
-- UTL_SMTP.write_data (c, 'This is a test message.' || TO_CHAR (i) || crlf);
-- END LOOP;
UTL_SMTP.write_data(c, v_mensaje || crlf);
UTL_SMTP.close_data (c);
UTL_SMTP.quit (c);
EXCEPTION WHEN OTHERS THEN
--UTL_SMTP.quit (c);
GP_AC_P_REGISTRA_LOG('PL','SEND_EMAIL',SYSDATE,USER,'E','error :'||SQLERRM);
DBMS_OUTPUT.PUT_LINE('ERROR: '||SQLERRM);
dbms_output.put_line( dbms_utility.format_error_backtrace );
END;
Thanks in advance for any help.
Kind regards.

Inno Setup check version of external application

What I'm trying to achieve is to check if Node.js is already is installed, and if so I wanna check for the version being up to date, let's say 8.x.x
From the question below I already achieved the initial check for it being installed at all. My Code looks pretty similar to the answer of the question.
Using Process Exit code to show error message for a specific File in [Run]
Now I'm struggling with reading the actual output of the node -v command (Expected result a string containing the version).
Is there a way to achieve that?
Running an application and parsing its output is rather inefficient way to check, if it exists and its version. Use FileSearch (node.exe is added to PATH) and GetVersionNumbers functions instead.
[Code]
function CheckNodeJs(var Message: string): Boolean;
var
NodeFileName: string;
NodeMS, NodeLS: Cardinal;
NodeMajorVersion, NodeMinorVersion: Cardinal;
begin
{ Search for node.exe in paths listed in PATH environment variable }
NodeFileName := FileSearch('node.exe', GetEnv('PATH'));
Result := (NodeFileName <> '');
if not Result then
begin
Message := 'Node.js not installed.';
end
else
begin
Log(Format('Found Node.js path %s', [NodeFileName]));
Result := GetVersionNumbers(NodeFileName, NodeMS, NodeLS);
if not Result then
begin
Message := Format('Cannot read Node.js version from %s', [NodeFileName]);
end
else
begin
{ NodeMS is 32-bit integer with high 16 bits holding major version and }
{ low 16 bits holding minor version }
{ shift 16 bits to the right to get major version }
NodeMajorVersion := NodeMS shr 16;
{ select only low 16 bits }
NodeMinorVersion := NodeMS and $FFFF;
Log(Format('Node.js version is %d.%d', [NodeMajorVersion, NodeMinorVersion]));
Result := (NodeMajorVersion >= 8);
if not Result then
begin
Message := 'Node.js is too old';
end
else
begin
Log('Node.js is up to date');
end;
end;
end;
end;
function InitializeSetup(): Boolean;
var
Message: string;
begin
Result := True;
if not CheckNodeJs(Message) then
begin
MsgBox(Message, mbError, MB_OK);
Result := False;
end;
end;
Since Inno Setup 6.1, you can use GetVersionComponents instead of GetVersionNumbers to avoid the bit magics.
For a similar question, see Checking if Chrome is installed and is of specific version using Inno Setup.

Verify permissions to run Inno Setup installer online

I am looking for a code for Inno Setup, that I can use to make my setup verify my permission to install the program. This code must check a text file on a web server.
If the file has the value "False", the setup has to cancel an installation and save the value in a registry file to cancel it always when Internet connection is not available.
If the file has the value "True", the setup will continue to install, and it will delete the registry file value if it exists.
If there is no Internet and the registry value does not exist the setup will continue to install.
Use InitializeSetup event function to trigger your check using HTTP request.
[Code]
const
SubkeyName = 'Software\My Program';
AllowInstallationValue = 'Allow Installation';
function IsInstallationAllowed: Boolean;
var
Url: string;
WinHttpReq: Variant;
S: string;
ResultDWord: Cardinal;
begin
try
WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
Url := 'https://www.example.com/can_install.txt';
WinHttpReq.Open('GET', Url, False);
WinHttpReq.Send('');
if WinHttpReq.Status <> 200 then
begin
RaiseException(
'HTTP Error: ' + IntToStr(WinHttpReq.Status) + ' ' + WinHttpReq.StatusText);
end
else
begin
S := Trim(WinHttpReq.ResponseText);
Log('HTTP Response: ' + S);
Result := (CompareText(S, 'true') = 0);
if RegWriteDWordValue(
HKLM, SubkeyName, AllowInstallationValue, Integer(Result)) then
Log('Cached response to registry')
else
Log('Error caching response to registry');
end;
except
Log('Error: ' + GetExceptionMessage);
if RegQueryDWordValue(HKLM, SubkeyName, AllowInstallationValue, ResultDWord) then
begin
Log('Online check failed, using cached result');
Result := (ResultDWord <> 0);
end
else
begin
Log('Online check failed, no cached result, allowing installation by default');
Result := True;
end;
end;
if Result then Log('Can install')
else Log('Cannot install');
end;
function InitializeSetup(): Boolean;
begin
Result := True;
if not IsInstallationAllowed then
begin
MsgBox('You cannot install this', mbError, MB_OK);
Result := False;
end;
end;

Inno Setup Load defaults for custom installation settings from a file (.inf) for silent installation

I have a setup script that allows the user to specify where they would like to install my application. It is in the form of a Pascal script within the [Code] block.
var
SelectUsersPage: TInputOptionWizardPage;
IsUpgrade : Boolean;
UpgradePage: TOutputMsgWizardPage;
procedure InitializeWizard();
var
AlreadyInstalledPath: String;
begin
{ Determine if it is an upgrade... }
{ Read from registry to know if this is a fresh install or an upgrade }
if RegQueryStringValue(HKLM, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppId}_is1', 'Inno Setup: App Path', AlreadyInstalledPath) then
begin
{ So, this is an upgrade set target directory as installed before }
WizardForm.DirEdit.Text := AlreadyInstalledPath;
{ and skip SelectUsersPage }
IsUpgrade := True;
{ Create a page to be viewed instead of Ready To Install }
UpgradePage := CreateOutputMsgPage(wpReady,
'Ready To Upgrade', 'Setup is now ready to upgrade {#MyAppName} on your computer.',
'Click Upgrade to continue, or click Back if you want to review or change any settings.');
end
else
begin
IsUpgrade:= False;
end;
{ Create a page to select between "Just Me" or "All Users" }
SelectUsersPage := CreateInputOptionPage(wpLicense,
'Select Users', 'For which users do you want to install the application?',
'Select whether you want to install the library for yourself or for all users of this computer. Click next to continue.',
True, False);
{ Add items }
SelectUsersPage.Add('All users');
SelectUsersPage.Add('Just me');
{ Set initial values (optional) }
SelectUsersPage.Values[0] := False;
SelectUsersPage.Values[1] := True;
end;
So the question is how could I support a silent installation? When a user invokes /SILENT or /VERYSILENT the installer defaults to SelectUsersPage.Values[1], which is for Just Me. I want to help support the user that wants to change the installation directory with providing an answer file.
I didn't develop all of this code, and am a newbie with Pascal.
Thanks.
You can add a custom key (say Users) to the .inf file created by the /SAVEINF.
Then in the installer, lookup the /LOADINF command-line argument and read the key and act accordingly:
procedure InitializeWizard();
var
InfFile: string;
I: Integer;
UsersDefault: Integer;
begin
...
InfFile := ExpandConstant('{param:LOADINF}');
UsersDefault := 0;
if InfFile <> '' then
begin
Log(Format('Reading INF file %s', [InfFile]));
UsersDefault :=
GetIniInt('Setup', 'Users', UsersDefault, 0, 0, ExpandFileName(InfFile));
Log(Format('Read default "Users" selection %d', [UsersDefault]));
end
else
begin
Log('No INF file');
end;
SelectUsersPage.Values[UsersDefault] := True;
end;

how to check port is free/open in inno setup script

how to check port is free /open in inno setup creation.
For example i tried to get os version GetWindowsVersionString()
Is there is any option is available to check if the port 8080 is free for installing tomcat service.
you can use my function to check port is free /open in inno setup
see :
function CheckPortOccupied(Port:String):Boolean;
var
ResultCode: Integer;
begin
Exec(ExpandConstant('{cmd}'), '/C netstat -na | findstr'+' /C:":'+Port+' "', '', 0,ewWaitUntilTerminated, ResultCode);
if ResultCode <> 1 then
begin
Log('this port('+Port+') is occupied');
Result := True;
end else
begin
Result := False;
end;
end;

Resources