I was playing with this code some time ago. The attachement works for me (I only made a few tests) but not for some of my friends. I don't know why (different mail server, mail client ?)
Code: Select all
; ==============================
; ENVOYER UN MAIL
; (SMTP) EN PUREBASIC
; ==============================
;
; ** USERLIB ** Uses RichEdit library
;
; ===========================
;-Compiler directives
; ===========================
; Pour Test
#Test64k = 0
; ===========================
;-Constantes
; ===========================
#Test64k = 0
; Window Constants
#Window = 0
#PleaseWait_Win = 1
; Gadget Constants
#Lbl_Envoyeur = 0
#String_Envoyeur = 1
#Lbl_Destinataire = 2
#String_Destinataire = 3
#Frame1 = 4
#Frame2 = 5
#Lbl_Serveur = 6
#String_Serveur = 7
#Lbl_Date = 8
#String_Date = 9
#RichEdit = 10
#Gadget_11 = 11
#Lbl_Objet = 12
#String_Objet = 13
#Btn_Envoyer = 14
#Btn_EffacerTexte = 15
#Gadget_16 = 16
#Frame3 = 17
#ListViewPJ = 18
#Btn_AjouterPJ = 19
#Btn_SupprimerPJ = 20
#PleaseWait_Text = 21
; ===========================
;-Variables
; ===========================
Global CrLf.s, ConnectionID.l, DateEnvoi.s, Copyright.s, Caption.s, PieceJointes.l
CrLf.s=Chr(13)+Chr(10)
Caption ="PG-Mail v0.01 Plus"
Copyright = "(c) Purebasic Forums / Gnozal" + CrLf
Copyright = Copyright + " Petit outil de messagerie ..."
Dim JourLibelle.s(6)
Jour.b = DayOfWeek(Date())
JourLibelle(0) = "Sun"
JourLibelle(1) = "Mon"
JourLibelle(2) = "Tue"
JourLibelle(3) = "Wed"
JourLibelle(4) = "Thu"
JourLibelle(5) = "Fri"
JourLibelle(6) = "Sat"
Mois.b = Month(Date()) - 1
Dim MoisLibelle.s(11)
MoisLibelle(0) = "Jan"
MoisLibelle(1) = "Feb"
MoisLibelle(2) = "Mar"
MoisLibelle(3) = "Apr"
MoisLibelle(4) = "May"
MoisLibelle(5) = "Jun"
MoisLibelle(6) = "Jul"
MoisLibelle(7) = "Aug"
MoisLibelle(8) = "Sep"
MoisLibelle(9) = "Oct"
MoisLibelle(10) = "Nov"
MoisLibelle(11) = "Dec"
TZInfo.TIME_ZONE_INFORMATION
; Bias is the number of minutes added To the local time To get GMT.
; Therefore, If Bias is 360, this indicates that we are 6 hours
; (360 minutes) _behind_ GMT (- 0600 GMT).
GetTimeZoneInformation_(TZInfo)
CorrectionGMT.s = Right("00" + Str(Abs(TZInfo\Bias) / 60), 2) + "00 GMT"
If TZInfo\Bias > 0
CorrectionGMT = " -" + CorrectionGMT
Else
CorrectionGMT = " +" + CorrectionGMT
EndIf
DateEnvoi = JourLibelle(Jour) + ", " + FormatDate("%dd", Date()) + " " + MoisLibelle(Mois) + " " + FormatDate("%yyyy %hh:%ii:%ss", Date()) + CorrectionGMT
; Linked lists
NewList Attachments.s()
; Fontes
Global FontID1
FontID1 = LoadFont(1, "Arial", 14, #PB_Font_Bold)
; ===========================
;-Procédures
; ===========================
; Procédures pour envoyer une pièce jointe
;
; Vérifier si un fichier est binaire (<> texte)
Procedure IsBinary(File.s)
If ReadFile(0, File)
While Loc() <> Lof()
CurrentByte.b = ReadByte()
If CurrentByte <= 9 Or CurrentByte = 127
ProcedureReturn 1
CloseFile(0)
EndIf
If CurrentByte > 10 And CurrentByte < 13
ProcedureReturn 1
CloseFile(0)
EndIf
If CurrentByte > 13 And CurrentByte < 32
ProcedureReturn 1
CloseFile(0)
EndIf
Wend
EndIf
EndProcedure
;==============================
; Trouver le type MIME pour une extension donnée
Procedure.s GetMIMEType(Extension.s)
Extension = "." + Extension
hKey.l = 0
KeyValue.s = Space(255)
DataSize.l = 255
If RegOpenKeyEx_(#HKEY_CLASSES_ROOT, Extension, 0, #KEY_READ, @hKey)
KeyValue = "application/octet-stream"
Else
If RegQueryValueEx_(hKey, "Content Type", 0, 0, @KeyValue, @DataSize)
KeyValue = "application/octet-stream"
Else
KeyValue = Left(KeyValue, DataSize-1)
EndIf
RegCloseKey_(hKey)
EndIf
ProcedureReturn KeyValue
EndProcedure
;==============================
; Envoyer données
Procedure Send(msg.s)
SendNetworkData(ConnectionID,@msg,Len(msg)) ; ConnectionID, *MemoryBuffer, Length
EndProcedure
;==============================
; Revevoir données
Procedure.s Wait()
res.s= Space(4999)
ReceiveNetworkData(ConnectionID,@res,4999) ; ConnectionID, *DataBuffer, DataBufferLength
res=Left(res,3)
ProcedureReturn res
EndProcedure
;==============================
; Envoyer mail
Procedure.l SendMail(ServeurMail.s,MailTo.s,MailFrom.s,Subject.s,MsgBody.s)
If InitNetwork()
ConnectionID = OpenNetworkConnection(ServeurMail,25) ; Serveur, Port
If ConnectionID
res.s=Wait()
error=0
If res="220"
Send("HELO Nowhere"+CrLf)
res=Wait()
If res="250"
Delay(10)
Send("MAIL FROM: <"+MailFrom+">"+CrLf)
res=Wait()
If res="250"
Send("RCPT TO: <"+MailTo+">"+CrLf)
res=Wait()
If res="250"
Send("DATA"+CrLf)
res=Wait()
If res="354"
Delay(10)
Send("Date: "+DateEnvoi+CrLf)
Send("From: <"+MailFrom+">"+CrLf)
Send("To: <"+MailTo+">"+CrLf)
Send("Subject: "+Subject+CrLf)
Send("X-Mailer: reliaM-X"+CrLf)
Send("MIME-Version: 1.0" +CrLf)
; Envoyer des pièces jointes ?
If PieceJointes
Debug "Email avec pièces jointes..."
Boundry.s = "reliaM-X_"+ FormatDate("%dd%mm%yyyy%hh%ii%ss", Date())
Send("Content-Type: multipart/mixed; boundary=" + Chr(34) + Boundry + Chr(13) + CrLf)
Send(CrLf)
; Corps du message
Debug "Message..."
Send("--" + Boundry + Chr(13) + Chr(10)) ; Boundry
Send("Content-Type: text/plain; charset=" + Chr(34) + "iso-8859-1" + Chr(34) + CrLf)
Send("Content-Transfer-Encoding: 7bit" + CrLf)
Send(CrLf)
Delay(10)
Send(MsgBody + CrLf)
Send(CrLf)
Delay(10)
Debug "Pièces jointes.."
ResetList(Attachments())
While(NextElement(Attachments()))
;Attachment headers
Send("--" + Boundry + CrLf) ; Boundry
Send("Content-Type: " + GetMIMEType(GetExtensionPart(Attachments())) + "; name=" + Chr(34) + GetFilePart(Attachments()) + Chr(34) + CrLf)
If IsBinary(Attachments()) ; Fichier binaire
Send("Content-Transfer-Encoding: base64" + CrLf)
Send("Content-Disposition: Attachment; filename=" + Chr(34) + GetFilePart(Attachments()) + Chr(34) + CrLf)
Send(CrLf)
Delay(10)
; Encoder les pièces jointes en Base64
If ReadFile(0, Attachments())
InputBufferLength.l = Lof()
If AllocateMemory(0, InputBufferLength, 0)
OutputBufferLength.l = InputBufferLength * 2 ; et pas * 1.33 comme dans le manuel !
If OutputBufferLength < 64
OutputBufferLength = 64
EndIf
If AllocateMemory(1, OutputBufferLength, 0)
ReadData(UseMemory(0), InputBufferLength)
Base64Encoder(UseMemory(0), InputBufferLength, UseMemory(1), OutputBufferLength)
CompilerIf #Test64k
Send(PeekS(UseMemory(1), OutputBufferLength) + CrLf) ; fonctionne seulement si chaîne < 64k
CompilerElse
; Déterminer la longeur de la chaîne (rechercher le zéro terminal)
LongueurChaine = 0
PointeurChaine.l = InputBufferLength
Repeat
If PeekB(UseMemory(1) + PointeurChaine) = 0
LongueurChaine = PointeurChaine
Break
EndIf
PointeurChaine = PointeurChaine + 1
ForEver
; On écrit dans le fichier par blocs de TailleBloc k
TailleBloc.l = 32768 ; <64k !
PointeurChaine = 0
While LongueurChaine > PointeurChaine
If (LongueurChaine - PointeurChaine) > TailleBloc
Send(PeekS(UseMemory(1) + PointeurChaine, TailleBloc))
PointeurChaine = PointeurChaine + TailleBloc
Else
Send(PeekS(UseMemory(1) + PointeurChaine, LongueurChaine - PointeurChaine))
Send(CrLf)
Break
EndIf
Wend
CompilerEndIf
Debug GetFilePart(Attachments()) + " (base64) Encoded"
FreeMemory(1)
Else
MessageRequester("ERREUR", "AllocateMemory [1] pour le fichier " + GetFilePart(Attachments()),#MB_ICONERROR)
ProcedureReturn 0
EndIf
FreeMemory(0)
Else
MessageRequester("ERREUR", "AllocateMemory [0] pour le fichier " + GetFilePart(Attachments()),#MB_ICONERROR)
ProcedureReturn 0
EndIf
CloseFile(0)
Else
MessageRequester("ERREUR", "Impossible d'ouvrir le fichier " + GetFilePart(Attachments()),#MB_ICONERROR)
ProcedureReturn 0
EndIf
Else ; Autre type de fichier (non binaire)
Send("Content-Transfer-Encoding: 7bit" + CrLf)
Send("Content-Disposition: Attachment; filename=" + Chr(34) + GetFilePart(Attachments()) + Chr(34) + CrLf)
Send(CrLf)
Delay(10)
If ReadFile(0, Attachments())
InputBufferLength.l = Lof()
If AllocateMemory(0, InputBufferLength, 0)
ReadData(UseMemory(0), InputBufferLength)
CompilerIf #Test64k
Send(PeekS(UseMemory(0), InputBufferLength) + CrLf) ; fonctionne seulement si chaîne < 64k
CompilerElse
LongueurChaine = InputBufferLength
; On écrit dans le fichier par blocs de TailleBloc k
TailleBloc.l = 32768 ; <64k !
PointeurChaine = 0
While LongueurChaine > PointeurChaine
If (LongueurChaine - PointeurChaine) > TailleBloc
Send(PeekS(UseMemory(0) + PointeurChaine, TailleBloc))
PointeurChaine = PointeurChaine + TailleBloc
Else
Send(PeekS(UseMemory(0) + PointeurChaine, LongueurChaine - PointeurChaine))
Send(CrLf)
Break
EndIf
Wend
CompilerEndIf
Debug GetFilePart(Attachments()) + " (7bit) Processed"
FreeMemory(0)
Else
MessageRequester("ERREUR", "AllocateMemory [0] pour le fichier " + GetFilePart(Attachments()),#MB_ICONERROR)
ProcedureReturn 0
EndIf
CloseFile(0)
Else
MessageRequester("ERREUR", "Impossible d'ouvrir le fichier " + GetFilePart(Attachments()),#MB_ICONERROR)
ProcedureReturn 0
EndIf
EndIf
Delay(10)
Send(CrLf)
Wend
Send("--" + Boundry + "--" + CrLf) ; End Boundry
Else ; Pas de pièces jointes
Debug "Processing messsage..."
Send("Content-Type: text/plain; charset=" + Chr(34) + "iso-8859-1" + Chr(34) + CrLf)
Send("Content-Transfer-Encoding: 7bit" + CrLf)
Send(CrLf)
Delay(10)
Send(MsgBody + CrLf)
EndIf
Delay(10)
Send(CrLf)
Send("."+ CrLf)
res=Wait()
If res="250"
Delay(10)
Send("QUIT"+CrLf)
res=Wait()
ProcedureReturn 1
Else
MessageRequester("ERREUR","TEXT ; erreur = " + res,#MB_ICONERROR)
EndIf
Else
MessageRequester("ERREUR","DATA ; erreur = " + res,#MB_ICONERROR)
EndIf
Else
MessageRequester("ERREUR","RCPT ; erreur = " + res,#MB_ICONERROR)
EndIf
Else
MessageRequester("ERREUR","MAIL FORM ; erreur = " + res,#MB_ICONERROR)
EndIf
Else
MessageRequester("ERREUR","HELO ; erreur = " + res,#MB_ICONERROR)
EndIf
Else
MessageRequester("ERREUR","Connection ; erreur = " + res,#MB_ICONERROR)
EndIf
CloseNetworkConnection(ConnectionID)
Else
MessageRequester("ERREUR","OpenNetworkConnection à <"+ServeurMail+"> a échoué !",#MB_ICONERROR)
EndIf
Else
MessageRequester("ERREUR","InitNetwork a échoué !",#MB_ICONERROR)
EndIf
EndProcedure
;==============================
; -----------------------------------------------------------
; Balloon tooltips
#TTM_SETTITLE = #WM_USER + 32
#TTS_BALLOON = $40
; Create Balloon Tooltip
Procedure.l AddBalloonTip(WindowHandle.l,GadgetHandle.l,Text.s,Title.s)
Balloon.l=CreateWindowEx_(0,"ToolTips_Class32","",$D0000000|#TTS_BALLOON,0,0,0,0,WindowHandle,0,GetModuleHandle_(0),0)
SendMessage_(Balloon,1044,0,0) ; ForeColor Tooltip
SendMessage_(Balloon,1043,$DFFFFF,0) ; BackColor Tooltip
SendMessage_(Balloon,1048,0,200) ; Maximum Width of tooltip
Parent.TOOLINFO\cbSize=SizeOf(TOOLINFO)
Parent\uFlags=$11
Parent\hwnd=GadgetHandle
Parent\uID=GadgetHandle
Parent\lpszText=@Text
SendMessage_(Balloon,$0404,0,Parent)
If Title <> ""
SendMessage_(Balloon,#TTM_SETTITLE ,1,@Title)
EndIf
ProcedureReturn Balloon
EndProcedure
; Change text of an existing ToolTip
Procedure ChangeBalloonToolTip(ToolTipHandle.l,GadgetHandle.l,Text.s,Title.s)
Parent.TOOLINFO\cbSize=SizeOf(TOOLINFO)
Parent\uFlags=$11
Parent\hwnd=GadgetHandle
Parent\uID=GadgetHandle
Parent\lpszText=@Text
SendMessage_(ToolTipHandle,$0404,0,Parent)
If Title <> ""
SendMessage_(ToolTipHandle,#TTM_SETTITLE ,1,@Title)
EndIf
EndProcedure
; -----------------------------------------------------------
; Afficher fenêtre principale
Procedure Open_Window()
If OpenWindow(#Window, 278, 66, 560, 566, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered, "PG-EFS_Mail Plus")
If CreateGadgetList(WindowID())
AddBalloonTip(WindowID(),WindowID(), Copyright,Caption)
TextGadget(#Lbl_Envoyeur, 10, 20, 60, 20, "Envoyeur :")
StringGadget(#String_Envoyeur, 70, 20, 200, 20, "QuidCustodiet@Custodies")
AddBalloonTip(WindowID(),GadgetID(#String_Envoyeur), "Envoyeur du mail [XXX@YYY]" + Chr(10) + "(Peut être fictif !)","")
TextGadget(#Lbl_Destinataire, 280, 20, 70, 20, "Destinataire :")
StringGadget(#String_Destinataire, 350, 20, 200, 20, "gnozal.test@test.fr")
AddBalloonTip(WindowID(),GadgetID(#String_Destinataire), "Destinataire(s) du mail [XXX@YYY]" + Chr(10) + "(Si plusieurs, les séparer par des ';')","")
Frame3DGadget(#Frame1, 0, 0, 560, 50, "Coordonnées")
Frame3DGadget(#Frame2, 0, 60, 560, 50, "Options")
TextGadget(#Lbl_Serveur, 10, 80, 50, 20, "Serveur :")
StringGadget(#String_Serveur, 70, 80, 130, 20, "TestSMTPServer")
AddBalloonTip(WindowID(),GadgetID(#String_Serveur), "Serveur de messagerie","")
TextGadget(#Lbl_Date, 210, 80, 40, 20, "Date :")
StringGadget(#String_Date, 250, 80, 300, 20, DateEnvoi)
AddBalloonTip(WindowID(),GadgetID(#String_Date), "Date [format particulier!]","")
Frame3DGadget(#Gadget_11, 0, 110, 560, 10, "")
TextGadget(#Lbl_Objet, 10, 130, 40, 20, "Objet :")
StringGadget(#String_Objet, 50, 130, 510, 20, "Test")
AddBalloonTip(WindowID(),GadgetID(#String_Objet), "Objet du message...","")
ButtonGadget(#Btn_Envoyer, 430, 530, 120, 30, "Envoyer message")
AddBalloonTip(WindowID(),GadgetID(#Btn_Envoyer), "Envoyer le mail...","")
ButtonGadget(#Btn_EffacerTexte, 10, 530, 110, 30, "Effacer texte")
AddBalloonTip(WindowID(),GadgetID(#Btn_EffacerTexte), "Effacer texte (Objet et Message)","")
Frame3DGadget(#Gadget_16, 0, 410, 560, 10, "")
Frame3DGadget(#Frame3, 0, 425, 560, 95, "Pièces jointes")
ListViewGadget(#ListViewPJ, 10, 445, 420, 65)
AddBalloonTip(WindowID(),GadgetID(#ListViewPJ), "Liste des pièces jointes [fichiers]","")
ButtonGadget(#Btn_AjouterPJ, 440, 445, 110, 30, "Ajouter pièce jointe")
AddBalloonTip(WindowID(),GadgetID(#Btn_AjouterPJ), "Ajouter un fichier dans les pièces jointes","")
ButtonGadget(#Btn_SupprimerPJ, 440, 480, 110, 30, "Supprimer pièce jointe")
AddBalloonTip(WindowID(),GadgetID(#Btn_SupprimerPJ), "Supprimer un fichier des pièces jointes","")
; RicheEdit
OpenRichEdit(WindowID(), #RichEdit, 0, 0, 0, 0, "Test")
RichEditID.l = RichEditID(0) ; récupérer le handle Windows
SetWindowLong_(RichEditID, #GWL_EXSTYLE, #WS_EX_CLIENTEDGE) ; ajouter des bords au RichEdit
ResizeRichEdit(#RichEdit, 0, 160, 560, 250)
RichEditFont(#RichEdit, "Courier New", -1, -1, 10, 0, 0, 0, 0) ; police 'Courier New' 10
AddBalloonTip(WindowID(),RichEditID,"Texte du message...","")
ActivateRichEdit(#RichEdit) ; donne le focus
EndIf
EndIf
EndProcedure
; Afficher fenêtre "d'attente"
Procedure Open_PleaseWait_Win()
If OpenWindow(#PleaseWait_Win, 263, 195, 227, 49, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered, "PG-EFS_Mail Plus")
If CreateGadgetList(WindowID())
TextGadget(#PleaseWait_Text, 5, 10, 215, 25, "Envoi en cours ...", #PB_Text_Center)
SetGadgetFont(#PleaseWait_Text, FontID1)
EndIf
EndIf
EndProcedure
; Fermer fenêtre "d'attente"
Procedure Close_PleaseWait_Win()
CloseWindow(#PleaseWait_Win)
EndProcedure
; Envoi du courrier
Procedure EnvoiCourrier(ServeurMail.s,Destinataire.s,Envoyeur.s,Sujet.s,Texte.s)
Ok.b = 1
If FindString(Destinataire, "@", 0) = 0
MessageRequester("ERREUR","Le destinataire <"+Destinataire+"> doit être xxx@yyy !",#MB_ICONERROR)
Ok = 0
EndIf
If FindString(Envoyeur, "@", 0) = 0
MessageRequester("ERREUR","L'envoyeur <"+Envoyeur+"> doit être xxx@yyy !",#MB_ICONERROR)
Ok = 0
EndIf
If Ok = 1
If SendMail(ServeurMail,Destinataire,Envoyeur,Sujet,Texte)
; MessageRequester("OK","Message envoyé à " + Destinataire + " !",0)
Else
MessageRequester("ERREUR","Message non envoyé à "+Destinataire+" !",#MB_ICONERROR)
EndIf
EndIf
EndProcedure
; ===========================
;-MAIN
; ===========================
Open_Window()
Repeat
EventID.l = WaitWindowEvent()
Select EventID
Case #PB_EventGadget
EventID2.l = EventGadgetID()
Select EventID2
Case #Btn_AjouterPJ ; Ajouter une pièce jointe
Fichier.s = OpenFileRequester("Ajouter une pièce jointe ...", Fichier, "Tous les fichiers|*.*", 0)
If Fichier <> ""
AddGadgetItem(#ListViewPJ, -1, Fichier)
EndIf
ActivateRichEdit(#RichEdit)
Case #Btn_SupprimerPJ ; Supprimer une pièce jointe
LigneChoisie.l = GetGadgetState(#ListViewPJ)
If LigneChoisie = -1
MessageRequester("ERREUR","Il faut choisir une pièce jointe à effacer !",#MB_ICONERROR)
Else
RemoveGadgetItem(#ListViewPJ, LigneChoisie)
EndIf
ActivateRichEdit(#RichEdit)
Case #Btn_Envoyer ; Envoyer message
; Préparer la liste des pièces jointes
PieceJointes = 0
TotalPieceJointes.l = CountGadgetItems(#ListViewPJ)
If TotalPieceJointes > 0
PieceJointes = 1
EndIf
If PieceJointes = 1
ClearList(Attachments.s())
For ix.l = 0 To TotalPieceJointes - 1
InsertElement(Attachments())
Attachments() = GetGadgetItemText(#ListViewPJ, ix, 0)
Next
EndIf
; Envoyer un mail à chaque destinataire
ServeurMail.s = Trim(GetGadgetText(#String_Serveur))
Envoyeur.s = Trim(GetGadgetText(#String_Envoyeur))
Sujet.s = GetGadgetText(#String_Objet)
Texte.s = GetRichEditText(#RichEdit, 0, -1)
DateEnvoi = GetGadgetText(#String_Date)
tmpDestinataire.s = Trim(GetGadgetText(#String_Destinataire))
NbDestinataires.b = 1
For tmpIndex.b = 1 To Len(tmpDestinataire)
If Mid(tmpDestinataire,tmpIndex,1)= ";"
NbDestinataires = NbDestinataires + 1
EndIf
Next
Open_PleaseWait_Win()
If NbDestinataires = 1
Destinataire.s = tmpDestinataire
EnvoiCourrier(ServeurMail,Destinataire,Envoyeur,Sujet,Texte)
Else
For tmpIndex.b = 1 To NbDestinataires
Destinataire = Trim(StringField(tmpDestinataire, tmpIndex, ";"))
EnvoiCourrier(ServeurMail,Destinataire,Envoyeur,Sujet,Texte)
Next
EndIf
Close_PleaseWait_Win()
MessageRequester("INFO","Envoi terminé",#MB_ICONINFORMATION)
ActivateRichEdit(#RichEdit)
Case #Btn_EffacerTexte ; Effacer les textes
SetGadgetText(#String_Objet,"")
SetRichEditText(#RichEdit, 0, -1, "")
ActivateRichEdit(#RichEdit)
EndSelect
Case #PB_EventCloseWindow ; Quitter
Quit.b = 1
EndSelect
Until Quit = 1
End
; -----------------------------------------------------------
; The end