Add attachment to message in Slack API - delphi

How can I add a large text file (actually a HTML file) as an attachment to a channel in Slack? A working example would be great. I use SDriver - the included demo works fine to send some strings, but I don't find anything on how to use attachments.
What I did so far:
procedure TForm1.SendActionExecute(Sender: TObject);
var
LWebHook: IMessageBuffer;
LMessage: IMessage;
LStopWatch: TStopWatch;
vAttachment: IAttachment;
vField: IFields;
begin
LStopWatch := TStopWatch.StartNew;
LMessage := TMessage.Create(EditMessage.Text + ' [' + TimeToStr(Now) + ']');
LMessage.UserName := EditUserName.Text;
LMessage.Icon_URL := EditIcon_URL.Text;
LMessage.Icon_Emoji := EditIcon_Emoji.Text;
LMessage.Channel := EditChannel.Text;
vAttachment := LMessage.AddAttachment;
vField := vAttachment.AddFields;
vField.Title := 'Title';
vField.Value := 'Value';
///////////////////////////////////////////////////////
// How can I add a large text file as attachment here ?
///////////////////////////////////////////////////////
LWebHook := TIncomingWebHook.Create(EditWebHookURL.Text, False);
LWebHook.Push(LMessage);
LWebHook.Flush;
end;

Related

DELPHI -how can i insert tlabeledit to dynamic tabsheet in TpageControl

i need to have this ini file which i mentioned it in my dynamic ttabsheet which i created it dynamically ! as you see ini file , it has three parts each start with 001-002-003 and then let those which start with 001 in first tabsheet , those start with 002 in second tabsheet and those start with 003 in thired tabsheet in my page control .
procedure TDlg_XRechnung.INIDatei_einlesen;
var NeueSeite : TTabSheet;
i,l: Integer;
begin
try
INIDatei := TIniFile.Create(INIDateiname);
Version := INIDatei.ReadInteger('INI','Version', 1);
DebugMode := INIDatei.ReadInteger('INI','DebugMode', 0);
PDFDatei := INIDatei.ReadString('PDF','PDFName', '');
XRechnungDatei := INIDatei.ReadString('PDF','XInvoice', '');
Edit_LeitwegeID.Text := INIDatei.ReadString('InvData','BT-10', '');
Edit_Bestellnummer.Text := INIDatei.ReadString('InvData','BT-13', '');
Edit_Projektreferenz.Text := INIDatei.ReadString('InvData','BT-11', '');
Edit_Vertragsnummer.Text := INIDatei.ReadString('InvData','BT-12', '');
Edit_Rechnungsnummer.Text := INIDatei.ReadString('InvData','BT-1', '');
Edit_Rechnungsdatum.Date := INIDatei.ReadDate('InvData','BT-2', now);
Edit_Leistungsdatum.Date := INIDatei.ReadDate('InvData','BT-9', now);
Edit_Bemerkung.Text := INIDatei.ReadString('InvData','BT-22', '');
Edit_Rechnungsersteller_Name.Text := INIDatei.ReadString('InvErst','BT-27', '');
Edit_Rechnungsersteller_UST_ID.Text := INIDatei.ReadString('InvErst','BT-31', '');
Edit_Rechnungsersteller_Adresse.Text := INIDatei.ReadString('InvErst','BT-35', '') + INIDatei.ReadString('InvErst','BT-36', '');
Edit_Rechnungsersteller_PLZ.Text := INIDatei.ReadString('InvErst','BT-38', '');
Edit_Rechnungsersteller_Ort.Text := INIDatei.ReadString('InvErst','BT-37', '');
Edit_Rechnungsersteller_Land.Text := INIDatei.ReadString('InvErst','BT-40', '');
Edit_Rechnungsempfänger_Name.Text := INIDatei.ReadString('InvEmp','BT-44','');
Edit_Rechnungsempfänger_Adresse.Text := INIDatei.ReadString('InvEmp','BT-50', '') + INIDatei.ReadString('InvEmp','BT-51', '');
Edit_Rechnungsempfänger_PLZ.Text := INIDatei.ReadString('InvEmp','BT-53', '');
Edit_Rechnungsempfänger_Ort.Text := INIDatei.ReadString('InvEmp','BT-52', '');
Edit_Rechnungsempfänger_Land.Text := INIDatei.ReadString('InvEmp','BT-55', '');
AnzahlPositinen := INIDatei.ReadInteger('POS','AnzPos', 1);
for i := 1 to AnzahlPositinen do
begin
NeueSeite := TTabSheet.Create(PC_Positionen);
NeueSeite.PageControl := PC_Positionen;
NeueSeite.Caption := 'Position ' + IntToStr(i);
end;
finally
INIDatei.Free;
end;
end;
this is my ini file
[POS]
AnzPos=3
;xxx ist die Zähl-Nr der Positionen mit Vornull
001BT-155=643
001BT-153=EID32 REI90-XC1-AN5C Bereich D
001BT-129=219,85
001BT-130=M2
001BT-152=19
001BT-146=43,50
001BT-154=EID 32/120 Spannbetondeckenplatte; d = 32 cmg
001BT-131=9563,48
001BT-132=11380,54
002BT-155=299
002BT-153=Auflagerstreifen 10X70X10
002BT-129=7
001BT-130=MTR
002BT-152=19
002BT-146=42,5
002BT-154=Hartgummiauflagerstreifen 10 x 70 mm auf 10 m Roll
002BT-131=297,5
002BT-132=354,03
003BT-155=40
003BT-153=Stahlwechsel, grundiert (F0
003BT-129=411.04
001BT-130=CMT
003BT-152=19
003BT-146=3,8
003BT-154=Stahlwechsel, grundiert (Flachstahl) Netto- nicht rabattierfähig.
003BT-131=1561.95
003BT-132=1858,72
i dont know how to do !? any idea ?
Thanks
You have every data in the [POS] section in the INI file you show while your code expact section [InvData]. Fix that.
In your PageControl, it is not enough to create TabSheet, you must also create a new frame instance to be hosted into each page. All frames are the same class and host edit, checkbox and so on to host data.
Then you must read the data, except count, inside you for-loop to create the page control. To read the data, you must combine the loop variable with fixed part to build the key. Something like this:
Edit1.Text := IniFile.ReadString('POS', Format('%03.3dBT-154', [I]), 'Some default value');
In my example, Edit1 is one field of the frame.

Uploading files using ICS component delphi

I am using HttpCli component form ICS to upload files using Delphi 7 ..
i copied code from example in the ICS folder .. tried to edit to let me upload files but got stuck on how to add the file to the file field name (filedata=c:\1.rar)
var
lData: TStringStream;
lDataOut : TMemoryStream;
lResultPage: string;
HttpCli1: THttpCli;
srv : string;
Data : AnsiString;
begin
HttpCli1 := THttpCli.Create(nil);
lDataOut := TMemoryStream.Create;
lData := TStringStream.Create('');
//A post request would use lDataout to post data to server
lDataOut.Seek(0, soFromBeginning);
httpcli1.SendStream := lDataOut;
httpcli1.RcvdStream := lData;
httpcli1.Cookie := memo2.Text;
httpcli1.URL := 'http://www.datafile.com/index.html';
try
httpcli1.get;
//lResultPage will contain the answer from the webserver as a string
lResultPage := lData.DataString;
// srv will contain upload URL ...
srv := ExtractBetween(lResultPage,'upload_url: "','"');
Data := 'Filename=' + UrlEncodeToA('Chrysanthemum.rar') + '&' +
'upload_type=' + UrlEncodeToA('file') + '&' +
'folder_id=0' + '&'+
'Filedata=' + '&' +
'Upload=' + UrlEncodeToA('Submit Query');
HttpCli1.SendStream := TMemoryStream.Create;
HttpCli1.SendStream.Write(Data[1], Length(Data));
HttpCli1.SendStream.Seek(0, 0);
HttpCli1.RcvdStream := lData;
HttpCli1.URL := srv;
HttpCli1.ContentTypePost := 'application/octet-stream';
HttpCli1.PostAsync;
except
lDataOut.Free;
Exit;
end;
lDataOut.Free;
lData.Free;
httpcli1.Free ;
end;
this how it should be ..
So I don't know how i add the file to the "fileData" in the postdata ...

Send email with MS Outlook don't add signature

I use Delphi RAD Studio 2010 and the next code to send email with Outlook:
procedure SendOutlookMail(email,subject,body,fileat:string);
const
olMailItem = 0;
var
vMailItem: variant;
Outlook: OutlookApplication;
NmSpace: NameSpace;
Folder: MAPIFolder;
begin
Outlook := CoOutlookApplication.Create;
NmSpace := Outlook.GetNamespace('MAPI');
NmSpace.Logon('', '', False, False);
Folder := NmSpace.GetDefaultFolder(olFolderInbox);
Folder.Display;
vMailItem := Outlook.CreateItem(olMailItem);
if email<>'' then vMailItem.Recipients.Add(email);
vMailItem.Subject := subject;
vMailItem.Body := Body;
vMailItem.Attachments.Add(fileat);
vMailItem.Display(false);
end;
It opens a new Outlook message and bring it to front to just press "Send" to send it. That's ok. The problem is, creating a new email message with this method doesn't add the signature. If I create a new message within Ms Outlook, the signature is added automatically.
Is there anyway I can add the signature that the user has configured in MS Outlook? (without adding the signature text to "Body" string variable). Thanks in advance.
the signature is added when you call MailItem.Display or access MailItem.GetInspecrtor.
Call MailItem.Display first (the signature will be added at that moment), then merge your data with the existing body. Note that setting the plain text Body property will wipe out formatting, so you will need to work with the HTMLBody property. Keep in mind that 2 HTML strings cannot be simply concatenated - read the HTMLBody property, find the appropriate insertion position (after the <body> tag?), then insert your data.
//Here is how I did it in Delphi. It shows the part no-one else did, which is //parsing the email HTML and putting your text above the signature.
//The part at the beginning loads up the string that I will be adding, so you //could ignore that.
procedure TfrmEngInfo2.CreateMSOutlookHoldEmail;
var
i: Integer;
Outlook: OleVariant;
Mail: OleVariant;
EmailTo,EmailCC: string;
SubjectLine: string;
PartNbr,PONbr,JobNbr: string;
HTMLInfo: string;
JobInfo: string;
x: integer;
iPos: integer;
RealPosition,GTPosition: integer;
const
olMailItem = 0;
olByValue = 1;
olFormatHTML = 2;
begin
SubjectLine := 'PCB Hold /';
if JOBHEMAI.state = dsInactive then
JOBHEMAI.open;
if CUST.state = dsInactive then CUST.open;
if RELEASE.FindKey([AdsQuery1.FieldByName('R-JOB#').asstring, AdsQuery1.FieldByName('R-RELEASE-NBR').asstring]) then
begin
PONbr := RELEASE.FieldByName('R-PO-NBR').asstring;
JobNbr := AdsQuery1.FieldByName('R-JOB#').asstring + AdsQuery1.FieldByName('R-RELEASE-NBR').asstring;
SubjectLine := SubjectLine + ' PO#: ' + PONbr + ' / ';
end;
if JOBHEMAI.FindKey([AdsQuery1.FieldByName('R-JOB#').asstring]) then
EmailTo := JOBHEMAI.FieldByName('HoldEmailAddress').asstring;
if HEADER.FindKey([AdsQuery1.FieldByName('R-JOB#').asstring]) then
begin
PartNbr := HEADER.FieldByName('H-PART#').asstring;
SubjectLine := SubjectLine + ' Part#: ' + PartNbr;
if CUST.FindKey([HEADER.FieldByName('H-CUST-NBR').asstring]) then
if EmailTo = '' then
EmailTo := CUST.FieldByName('HoldEmailAddress').asstring;
if SALEPRSN.FindKey([HEADER.FieldByName('H-SLMN#').asstring]) then
EmailCC := SALEPRSN.fieldByName('E-mail').asstring;
end;
SubjectLine := SubjectLine + JobNbr;
try
Outlook := GetActiveOleObject('Outlook.Application');
except
Outlook := CreateOleObject('Outlook.Application');
end;
JobInfo := 'We have released the hold for your job Part: ' + PartNbr + ' PO: ' + PONbr
+ 'Job Number: ' + JobNbr;
Mail := Outlook.CreateItem(olMailItem);
Mail.To := EmailTo;
Mail.cc := EmailCC;
Mail.Subject := SubjectLine;
// Main.Attachments.Add('c:\test.jpg', olByValue, 1, 'My Test Image');
Mail.BodyFormat := olFormatHTML;
//This load the HTMLBody with all the outlook stuff including the users signature. Basically a blank email message
Mail.GetInspector;
// Find the position of the opening <body command.
x := pos('<body',Mail.HTMLBody);
// Put the HTMLBody in to a string field so we can examine it.
HTMLInfo := Mail.HTMLBody;
// Now loop through and find the position of the closing tag. '>' It must be in a position greater than the starting tag
RealPosition := 0;
while pos('>',HTMLInfo) > 0 do
begin
GTPosition := pos('>',HTMLInfo);
RealPosition := RealPosition + GTPosition;
if RealPosition > x then
break;
HTMLInfo := copy(HTMLInfo,GTPosition + 1,Length(HTMLInfo) - GTPosition);
end;
// Since we destroyed the HTMLInfo in the analysis, load it again.
HTMLInfo := Mail.HTMLBody;
// Now insert our information at the right spot.
insert(JobInfo,HTMLInfo,RealPosition + 1);
// Now load the modified HTMLInfo back to the Mail.HTMLBody so that it can display in the message.
Mail.HTMLBody := HTMLInfo;
// Finally display the Outlook Email
Mail.Display;
Outlook := unassigned;
end;

Why is Indy not retrieving some of my mailbodies

I have the following code I use for retrieving mails from a POP3 account.
It is working very well most of the time, but from time to time there are some mails where it doesn't retrieve the body.
If I test the IdMessage.MessageParts.Count it says that it is 0 - if I use another mailclient to retrieve the mail there is no problem.
I have a TIdPOP3 and a TIdMessage component on the form.
The connection is OK as there may be some mails that are show OK.
I can't figure out any system in which mails are not shown correct and which are not. But there might be one.
I use Delphi XE3 and the Indy is version 10.5.9.0
procedure TfrmJsMailCollect.lstMailsClick(Sender: TObject);
var
MailBody: string;
intIndex: integer;
begin
if (lstMails.Items.Count = 0) or (lstMails.SelCount = 0) then
Exit;
MailBody := '';
try
begin
mmoBody.Clear;
lstMails.Selected.SubItems.Strings[0];
lstMails.Selected.ImageIndex := 4;
conPOP3.Retrieve(lstMails.Selected.Index + 1, IdMessage);
for intIndex := 0 To Pred(IdMessage.MessageParts.Count) do
begin
if (IdMessage.MessageParts.Items[intIndex] is TIdAttachmentFile) then
begin // Attachments are skipped
end
else
begin // body text
if Pos('text/plain', IdMessage.MessageParts.Items[intIndex].ContentType) <> 0 then
begin
if TIdText(IdMessage.MessageParts.Items[intIndex]).Body.Text <> '' then
begin
MailBody := MailBody + TIdText(IdMessage.MessageParts.Items[intIndex]).Body.Text;
mmoBody.Lines.Add(MailBody);
MemoValidate;
end;
end;
end;
end;
end;
mmoBody.CaretPos.SetLocation(0, 0);
Application.ProcessMessages;
except
Logfile.Error('F_JsMailCollect.lstMailsClick - ' + cxGetResourceString(#sLangPop3ErrorReading));
end;
end;
With advice from Remy Lebeau and searching the web I ended up with the code below. This does the trick for now, but I would like to improve it so that the memo on my form only shows a nice message that would be readable for everyone - but that may come later.
procedure TfrmJsMailCollect.lstMailsClick(Sender: TObject);
var
MailBody: string;
i: integer;
ContentType: string;
begin
if (lstMails.Items.Count = 0) or (lstMails.SelCount = 0) then
Exit;
try
MailBody := '';
mmoBody.Clear;
lstMails.Selected.SubItems.Strings[0];
lstMails.Selected.ImageIndex := 4;
conPOP3.Retrieve(lstMails.Selected.Index + 1, IdMessage);
ContentType := IdMessage.ContentType;
case PosInStrArray(ContentType, ['multipart/mixed', 'multipart/alternative', 'text/html', 'text/plain'], False) of
0: begin { multipart/mixed }
for i := 0 To Pred(IdMessage.MessageParts.Count) do
begin
if TIdText(IdMessage.MessageParts.Items[i]).Body.Text <> '' then
begin
MailBody := MailBody + TIdText(IdMessage.MessageParts.Items[i]).Body.Text;
mmoBody.Lines.Add(MailBody);
MemoValidate;
end;
end;
end;
1: begin { multipart/alternative }
for i := 0 To Pred(IdMessage.MessageParts.Count) do
begin
if TIdText(IdMessage.MessageParts.Items[i]).Body.Text <> '' then
begin
MailBody := MailBody + TIdText(IdMessage.MessageParts.Items[i]).Body.Text;
mmoBody.Lines.Add(MailBody);
MemoValidate;
end;
end;
end;
2: begin { text/html }
mmoBody.Lines := IdMessage.Body;
MemoValidate;
end;
3: begin { text/plain }
mmoBody.Lines := IdMessage.Body;
MemoValidate;
end;
else
// nothing supported to display...
end;
mmoBody.CaretPos.SetLocation(0, 0);
Application.ProcessMessages;
except
Logfile.Error('F_JsMailCollect.lstMailsClick - ' + cxGetResourceString(#sLangPop3ErrorReading));
end;
end;
Not all email content is parsed into the TIdMessage.MessageParts collection. MIME parts and attachments are, but other content gets parsed into the TIdMessage.Body instead, which you are completely ignoring. You need to look at the TIdMessage.ContentType when deciding where to extract content from. Attachments will always be in TIdMessage.MessageParts, but text may or may not be, depending on the TIdMessage.ContentType.

How can I read email with HTML format in a Delphi application?

I have created a program that can read email from Exchange 2007. However, it can only read the body of the email in plain-text format. When I tried to retrieve email in HTML format, my software cannot read the body and it always blank. I am using Delphi 2007 and IMAP 9.
Update:
Here is my code:
procedure TForm1.tmrCekTimer(Sender: TObject);
var
TheFlags: TIdMessageFlagsSet;
TheUID: string;
TheMsg: TIdMessage;
MailBoxName: string;
MyClass: TComponent;
begin
MailBoxName := 'INBOX';
if TheImap.SelectMailBox(MailBoxName) = False then
begin
Screen.Cursor := crDefault;
ShowMessage('Error selecting '+MailBoxName);
Exit;
end;
TheMsg := TIdMessage.Create(nil);
nCount := TheImap.MailBox.TotalMsgs;
TheMsg.ContentType := 'multipart/alternative';
TheMsg.Encoding := meMime;
if nCount = 0 then begin
StringGrid1.RowCount := 2;
StringGrid1.Cells[0, 1] := '';
StringGrid1.Cells[1, 1] := '';
StringGrid1.Cells[2, 1] := '';
StringGrid1.Cells[3, 1] := '';
ShowMessage('There are no messages in '+MailBoxName);
end else begin
StringGrid1.RowCount := nCount + 1;
for i := 0 to nCount-1 do begin
TheImap.GetUID(i+1, TheUID);
TheImap.UIDRetrieveFlags(TheUID, TheFlags);
TheImap.UIDRetrieve(TheUID, TheMsg);
//TheImap.UIDRetrieveHeader(TheUID, TheMsg);
StringGrid1.Cells[0, i+1] := IntToStr(i+1);
StringGrid1.Cells[1, i+1] := TheMsg.From.Address;
//StringGrid1.Cells[1, i+1] := TheUID;
if mfSeen in TheFlags then
StringGrid1.Cells[2, i+1] := 'Yes'
else begin
StringGrid1.Cells[2, i+1] := 'No';
end;
end;
end;
The contents of MIME-encoded emails, such as HTML emails (if plain-text and/or attachments are also present) are stored in the TIdMessage.MessageParts property, not in the TIdMessage.Body property. You need to look at the email's actual ContentType property to know which property TIdMessage parsed the email into.
Using MAPI, I usually try to get the PR_BODY_HTML property as string; if that’s empty, I retrieve the PR_HTML property.
const
PR_HTML = $10130102;
PR_BODY_HTML = $1013001E;
This usually works for me. Of course, maybe you’re using different technology altogether, but you’re not giving us much to work with...

Resources