Jump to content

Check Gmail Emails


Recommended Posts

I'm curious, did you get anything working? because believe it or not I was trying to find a way to do this as well, the furthest I got was being able to read the atom feed but I'm still stuck at trying to read the full email, I tried using winapiex.au3 to authenticate to Google but I can't figure it out :S

I'd have posted this earlier but I was too inebriated to post it and make sense.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_Run_Obfuscator=y
#Obfuscator_Parameters=/so
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <string.au3>

Global $eReturn = _CheckMail("email", "password")
Global $Emails = @extended

Switch @error
    Case 0
        Switch @extended
            Case True
                ConsoleWrite("   0>"&$eReturn[0][0] & @CR)
                ConsoleWrite("   "& $Emails & " " & $eReturn[0][1] & @CR)
                For $x = 1 To $Emails
                    ConsoleWrite("!>Title   - " & $eReturn[$x][0] & @CR)
                    ConsoleWrite("+>Name    - " & $eReturn[$x][1] & @CR)
                    ConsoleWrite("->Email   - " & $eReturn[$x][2] & @CR)
                    ConsoleWrite(">summary - " & $eReturn[$x][3] & @CR & @CR)
                Next
            Case Else
                MsgBox(64,"success!","Success! But you have no new emails :(")
        EndSwitch
    Case 1
        MsgBox(0,"Error!","Couldn't get your new emails for some reason...")
    Case 2,3
        MsgBox(0,"Error!","you need to enter an user name and password!")
    Case 4
        MsgBox(16,"Error!","Error Getting URL Source!")
    Case 5
        MsgBox(16,"Error!","No response?")
    Case 6
        MsgBox(16,"Error!","Unauthorized access, possibly a wrong username or password!")
EndSwitch

; #FUNCTION# ====================================================================================================================
; Name ..........: _CheckMail
; Description ...: Checks a Google Email for new emails.
; Syntax ........: _CheckMail($UserName, $Pswd[, $UserAgentString = ""])
; Parameters ....: $UserName            - An unknown value.
;                 $Pswd             - An unknown value.
;                 $UserAgentString   - [optional] An unknown value. Default is "".
; Return values .: A 2d array with email information as follows~
;                   1|Title
;                   2|Name
;                   3|Email
;                   4|Summary
;                   5|Date
;                   6|Time
;
; Author ........: dantay9
; Modified ......: THAT1ANONYMOUSDUDE
; Remarks .......:
; Related .......:
; Link ..........: http://www.autoitscript.com/forum/topic/111853-gmail-email-checker/page__view__findpost__p__819409
; Example .......: Yes
; ===============================================================================================================================

Func _CheckMail($UserName, $Pswd, $UserAgentString = "")
    If Not $UserName Then Return SetError(2,0,0)
    If Not $Pswd Then Return SetError(3,0,0)
    If $UserAgentString Then HttpSetUserAgent($UserAgentString)
    Local $source = InetRead("https://" & $UserName & ":" & $Pswd & "@gmail.google.com/gmail/feed/atom",1)
    If @error Then
        ConsoleWrite("!>Error Getting URL Source!" & @CR & "     404>@Error =" & @error & @CR & "    404>@Extended =" & @extended & @CR)
        Return SetError(4,0,0)
    EndIf
    If $source Then
        $source = BinaryToString($source)
    Else
        Return SetError(5,0,0)
    EndIf
    If StringLeft(StringStripWS($source, 8), 46) == "<HTML><HEAD><TITLE>Unauthorized</TITLE></HEAD>" Then  Return SetError(6, 0, 0)
    If Not Number(StringBetween($source, "<fullcount>", "</fullcount>")) Then Return SetError(0,0,0)
    Local $Email = _StringBetween($source, "<entry>", "</entry>")
    If @error Then Return SetError(1, 0, 0)
    Local $Time
    Local $Count = UBound($Email)
    Local $Datum[$Count + 1][6]
    $Datum[0][0] = StringBetween($source, "<title>", "</title>")
    $Datum[0][1] = StringBetween($source, "<tagline>", "</tagline>")
    For $i = 0 To $Count - 1
        $Datum[$i+1][0] = StringBetween($Email[$i], "<title>", "</title>")
        If Not $Datum[$i+1][0] Then $Datum[$i][0] = "(no subject)"
        $Datum[$i+1][1] = StringBetween($Email[$i], "<name>", "</name>")
        $Datum[$i+1][2] = StringBetween($Email[$i], "<email>", "</email>")
        $Datum[$i+1][3] = StringBetween($Email[$i], "<summary>", "</summary>")
        $Time = StringBetween($Email[$i], "<issued>", "</issued>")
        $Datum[$i+1][4] = DateFromTimeDate($Time)
        $Datum[$i+1][5] = TimeFromTimeDate($Time)
    Next
    Return SetError(0,$Count,$Datum)
EndFunc
Func StringBetween($Str, $S, $E)
    Local $B = _StringBetween($Str, $S, $E)
    If @error Then Return SetError(1,0,0)
    Return SetError(0,0,$B[0])
EndFunc   ;==>StringBetween

; #FUNCTION# ====================================================================================================================
; Name ..........: DateFromTimeDate
; Description ...: Returns email sent date.
; Syntax ........: DateFromTimeDate($String)
; Parameters ....: $String            - A gmail date string
; Return values .: None
; Author ........: ???
; Example .......: No
; ===============================================================================================================================

Func DateFromTimeDate($String)
    Local $RegEx = StringRegExp($String, "(?<Year>d{2}|d{4})(?:-)(?<Month>d{1,2})(?:-)(?<Day>d{1,2})", 1)
    If IsArray($RegEx) Then
        Return Int($RegEx[0]) & "/" & Int($RegEx[1]) & "/" & Int($RegEx[2])
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>DateFromTimeDate

; #FUNCTION# ====================================================================================================================

; Name ..........: TimeFromTimeDate
; Description ...: Returns the email sent time.
; Syntax ........: TimeFromTimeDate($String)
; Parameters ....: $String            - An unknown value.
; Return values .: None
; Author ........: ???
; Example .......: No
; ===============================================================================================================================

Func TimeFromTimeDate($String)
    Local $RegEx = StringRegExp($String, "(?<Hour>d{1,2})(?::)(?<Minute>d{1,2})(?::)(?<Second>d{1,2})", 1)
    If IsArray($RegEx) Then
        Return (Int($RegEx[0]) - 4) & ":" & Int($RegEx[1]) & ":" & Int($RegEx[2]) ;don't know why I have to subtract 4
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>TimeFromTimeDate
Edited by Skitty
Link to comment
Share on other sites

  • Moderators

Am I completely wrong, or is your solution not automating the login to GMail so you can read the email??

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

Am I completely wrong, or is your solution not automating the login to GMail so you can read the email??

It's not working for you? or what do you mean?

Edit: haha, stupid me, I posted my gmail password and let everyone read my emails there, again. no worries...

Edited by THAT1ANONYMOUSEDUDE
Link to comment
Share on other sites

  • Moderators

I mean, the forum rules explicitly state no discussion of auto-login methods. Unless I am wrong, your solution violates this.

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

I mean, the forum rules explicitly state no discussion of auto-login methods. Unless I am wrong, your solution violates this.

Oh, you mean that, I was under the impression that it was ok to do this with gmail, especially since there are examples set in the documentation for winhttp.au3 by the autoit developers..

Cookies are sessions' properties. You don't set them your self unless overwriting them.

Both _WinHttpSendRequest and _WinHttpSimpleSSLRequest have examples of gmail login.

What exactly you want to do?

Edited by THAT1ANONYMOUSEDUDE
Link to comment
Share on other sites

  • Moderators

I asked a Mod to weigh in. Things may have changed since those were written.

Edited by JLogan3o13

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

This seems pretty specific. The ATOM feed is read-only. The login method being used is trivial. It's also documented (though deprecated I think). It's also using a clearly supported API for programs to access as opposed to simulating a human performing a conventional login.

In other words, this is fine.

Link to comment
Share on other sites

This seems pretty specific. The ATOM feed is read-only. The login method being used is trivial. It's also documented (though deprecated I think). It's also using a clearly supported API for programs to access as opposed to simulating a human performing a conventional login.

In other words, this is fine.

Well, now that this is cleared, then I guess I can continue in my attempt to get the full email data?

and by btw, I was going to PM you but I know how you guys hate that, I wanted to ask...

Can I post a script to the examples section that recovers Google Chrome stored passwords/login data? I know it can be used for malicious purposes but what if I just post a compiled obfuscated binary so as to avoid the obvious?

Link to comment
Share on other sites

Can I post a script to the examples section that recovers Google Chrome stored passwords/login data? I know it can be used for malicious purposes but what if I just post a compiled obfuscated binary so as to avoid the obvious?

No.
Link to comment
Share on other sites

  • 2 weeks later...

Thank you so much apud.

Just wondering though, would it be possible to make it download an attachment from the first unread email or would that be impossible? =/

Sorry for being annoying.

Thank you so much again =D

No, of course it's not impossible, but the bad news is that I seem to be the only one willing to touch this subject and I so happen to not understand how to use winhttp sessions which seem to be needed for doing this. I tried it, I really did, But I just can't f***ing understand what the hell I need to do to read the full email, I keep getting a server response code saying that I'm unauthorized, I even skimmed through several gmail reader extensions for chrome and didn't really find out how they were doing it.

Apparently one needs to login to authenticate ones self and in response, google gives you a cookie as it seems, what I'm stumped at is how the heck should I use that damn cookie to tell google I've already logged in so I can read them.

Edited by ApudAngelorum
Link to comment
Share on other sites

I have tried searching through the source code of the message link returned from _CheckMail() and also tried checking source using:

$oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
$oHTTP.Open("GET","LINKRETURNEDFROM_CHECKMAIL()")
$oHTTP.Send()
$HTMLSource = $oHTTP.Responsetext
ConsoleWrite($HTMLSource)

I got just the preview that comes with atom. None of the message was present using winhttp...

Link to comment
Share on other sites

I thought I would combine Melba23's Notify UDF and ApudAngelorum's Modified CheckMail UDF here to notify of a new E-mail but I'm getting stuck if someone deletes a Email then a new one arrives.

My horrible script:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=..Downloadsgmail.ico
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#Obfuscator_Parameters=/so
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <string.au3>
#include "Notify.au3"
#include "CheckGmail.au3"

Global $eReturn
Global $Emails = @extended
Global $Count, $NumberofEmails = 0
Global $User = InputBox("Gmail", "Please enter user name.")
Global $Pass = InputBox("Gmail", "Please enter password.", "", "*")

_Display()
_Notify_RegMsg()
_Notify_Locate(0)
AdlibRegister("_Display", 5000)
_Notify_Set(Default)

While 1
Sleep(10)
If $NumberofEmails < $Count Then
For $x = $NumberofEmails To $Count
_Notify_Show(@AutoItExe, "", $eReturn[$x][1] & @CR & $eReturn[$x][0])
Next
$NumberofEmails = $Count
ElseIf $NumberofEmails > $Count Then
$NumberofEmails = $Count
EndIf
WEnd

Func _Display()
$eReturn = _CheckMail($User, $Pass)
Switch @error
Case 1
MsgBox(0,"Error!","Couldn't get your new emails for some reason...")
Exit
Case 2,3
MsgBox(0,"Error!","you need to enter an user name and password!")
Exit
Case 4
MsgBox(16,"Error!","Error Getting URL Source!")
Exit
Case 5
MsgBox(16,"Error!","No response?")
Exit
Case 6
MsgBox(16,"Error!","Unauthorized access, possibly a wrong username or password!")
Exit
EndSwitch
EndFunc

Melba23's Notify UDF:

#include-once

; #INDEX# ============================================================================================================
; Title .........: Notify
; AutoIt Version : 3.3.2.0+ - uses AdlibRegister/Unregister
; Language ......: English
; Description ...: Show and hides pop-out notifications from the side of the screen in user defined colours and fonts
; Author(s) .....: Melba23 - credit to UEZ for the PNG code
; ====================================================================================================================

;#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

; #INCLUDES# =========================================================================================================
#include <StringSize.au3>
#include <GDIPlus.au3>

; #GLOBAL VARIABLES# =================================================================================================
; Create array to hold data for Notifications
; [0][0] = Count            [n][0] = Handle
; [0][1] = Max avail        [n][1] = Timer duration
; [0][2] = X-coord          [n][2] = Timer stamp
; [0][3] = Low Y-coord      [n][3] = Clickable
; [0][4] = Location         [n][4] = X-Coord
Global $aNotify_Data[1][5] = [[0, Int((@DesktopHeight - 60) / 50), @DesktopWidth - 10, @DesktopHeight - 10, 0]]
; Adjust values according to taskbar position and desired location
_Notify_Locate(0)

; Create array to hold default and current Notification values = [Style ($SS_CENTER), Col, BkCol, Font, Slide, Interference]
; [0][5] = Timer running, [1][5] = Click running
Global $aNotify_Settings[2][6] = [[1, 0, 0, _Notify_GetDefFont(), False, False], [0, 0, 0, 0, 0, False]]
Global $aNotify_Ret = DllCall("User32.dll", "int", "GetSysColor", "int", 8) ; $COLOR_WINDOWTEXT = 8
$aNotify_Settings[0][1] = $aNotify_Ret[0]
$aNotify_Ret = DllCall("User32.dll", "int", "GetSysColor", "int", 5) ; $COLOR_WINDOW = 5
$aNotify_Settings[0][2] = $aNotify_Ret[0]
; Use the defaults as current settings
For $i = 0 To 3
    $aNotify_Settings[1][$i] = $aNotify_Settings[0][$i]
Next

; #CURRENT# ==========================================================================================================
; _Notify_Locate: Determine notification start position, direction of movement and maximum number
; _Notify_Set:    Sets text justification and optionally colours and font for notifications
; _Notify_Show:   Shows a notification
; _Notify_Hide:   Hides a notification
; _Notify_RegMsg: Registers the WM_MOUSEACTIVATE message to enable retraction of the notification on clicking
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _Notify_Timer:            Checks whether a notification has timed out
; _Notify_WM_MOUSEACTIVATE: Message handler to check if notification clicked
; _Notify_Delete:           Retract a notification when timed out or clicked
; _Notify_Reset:            Reposition remaining notifications on screen
; _Notify_GetDefFont:       Determine system default MsgBox font
; _Show_PNG:                Set PNG as image
; _BitmapCreateDIB:         Create bitmap
; ====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _Notify_Locate
; Description ...: Determine notification start position, direction of movement and maximum number
; Syntax ........: _Notify_Locate($iLocation)
; Parameters ....: $iLocation - Start point and direction for Notifications
;                              0 = Bottom right upwards (default)
;                              1 = Top right downwards
;                              2 = Top left downwards
;                              3 = Bottom left upwards
; Requirement(s).: v3.3.2.0 or higher - AdlibRegister/Unregister used in _Notify_Show
; Return values .: Success - Returns 1
;                 Failure - Returns 0 and sets @error as follows
;                           1 = Notificatiosn displayed
;                           2 = Invalid parameter
; Author ........: Melba23
; Remarks .......: This function will only set or reset the location if no notificatiosn are displayed
; Example........: Yes
; ===============================================================================================================================
Func _Notify_Locate($iLocation)

    ; Can only reset notification location when no notifications are displayed
    If $aNotify_Data[0][0] Then
        Return SetError(1, 0, 0)
    EndIf

    ; Check valid parameter
    Switch $iLocation
        Case 0 To 3
            $aNotify_Data[0][4] = $iLocation
        Case Else
            Return SetError(2, 0, 0)
    EndSwitch

    Local $tWorkArea
    ; Determine which struct syntax to use to use
    If @AutoItVersion < "3.3.8.0" Then
        $tWorkArea = DllStructCreate("long Left;long Top;long Right;long Bottom")
    Else
        $tWorkArea = DllStructCreate("struct;long Left;long Top;long Right;long Bottom;endstruct")
    EndIf
    ; Check if Taskbar is hidden
    Local $aRet = DllCall("shell32.dll", "uint", "SHAppBarMessage", "dword", 0x00000004, "ptr*", 0) ; $ABM_GETSTATE
    If BitAND($aRet[0], 0x01) Then

        ; Set max number available
        $aNotify_Data[0][1] = Int((@DesktopHeight - 60) / 50)

        ; Adjust data array depending on required location
        Switch $iLocation
            Case 0 ; From bottom right
                $aNotify_Data[0][3] = @DesktopHeight - 10 ; bottom Y
                $aNotify_Data[0][2] = @DesktopWidth - 10  ; right X
            Case 1 ; From top right
                $aNotify_Data[0][3] = 10                  ; top Y
                $aNotify_Data[0][2] = @DesktopWidth - 10  ; right X
            Case 2 ; From top left
                $aNotify_Data[0][3] = 10                  ; top Y
                $aNotify_Data[0][2] = 10                  ; left X
            Case 3 ; From bottom left
                $aNotify_Data[0][3] = @DesktopHeight - 10 ; bottom Y
                $aNotify_Data[0][2] = 10                  ; left X
        EndSwitch

    Else

        ; Determine available work area ; $SPI_GETWORKAREA = 48
        DllCall("user32.dll", "bool", "SystemParametersInfoW", "uint", 48, "uint", 0, "ptr", DllStructGetPtr($tWorkArea), "uint", 0)
        If @error Then Return SetError(2, 0, -1)
        Local $aWorkArea[4] = [DllStructGetData($tWorkArea, "Left"), DllStructGetData($tWorkArea, "Top"), _
            DllStructGetData($tWorkArea, "Right"), DllStructGetData($tWorkArea, "Bottom")]

        ; Set max number available
        $aNotify_Data[0][1] = Int(($aWorkArea[3] - $aWorkArea[1] - 60) / 50)

        ; Adjust data array depending on required location
        Switch $iLocation
            Case 0 ; From bottom right
                $aNotify_Data[0][3] = $aWorkArea[3] - 10 ; bottom Y
                $aNotify_Data[0][2] = $aWorkArea[2] - 10 ; right X
            Case 1 ; From top right
                $aNotify_Data[0][3] = $aWorkArea[1] + 10 ; top Y
                $aNotify_Data[0][2] = $aWorkArea[2] - 10 ; right X
            Case 2 ; From top left
                $aNotify_Data[0][3] = $aWorkArea[1] + 10 ; top Y
                $aNotify_Data[0][2] = $aWorkArea[0] + 10 ; left X
            Case 3 ; From bottom left
                $aNotify_Data[0][3] = $aWorkArea[3] - 10 ; bottom Y
                $aNotify_Data[0][2] = $aWorkArea[0] + 10 ; left X
        EndSwitch

    EndIf

    Return 1

EndFunc   ;==>_Notify_Locate

; #FUNCTION# =========================================================================================================
; Name...........: _Notify_Set
; Description ...: Sets text justification and optionally colours, font and movement for notifications
; Syntax.........: _Notify_Set($vJust, [$iCol, [$iBkCol, [$iFont_Name, [$fSlide]]])
; Parameters ....: $vJust    - 0 = Left justified, 1 = Centred (Default), 2 = Right justified
;                               Can use $SS_LEFT, $SS_CENTER, $SS_RIGHT
;                      >>>>>    Setting this parameter to "Default" will reset ALL parameters to default values  <<<<<
;                      >>>>>    All optional parameters default to system MsgBox default values                  <<<<<
;                 $iCol   - [Optional] The colour for the notification text
;                 $iBkCol - [Optional] The colour for the notification background
;                               Omitting a colour parameter or setting it to -1 leaves it unchanged
;                               Setting a colour parameter to Default resets the system colour
;                 $sFont_Name - [Optional] The font to use for the notification
;                      >>>>>    Omitting this parameter leaves it unchanged                                      <<<<<
;                      >>>>>    Setting this parameter to Default resets the system message box font                <<<<<
;                 $fSlide - [Optional] Movement of notifications into new position when one retracts
;                               False = Instant (default)
;                               True  = Slide
;                      >>>>>    Using this option increases the chances of a system crash - user beware!!          <<<<<
; Requirement(s).: v3.3.2.0 or higher - AdlibRegister/Unregister used in _Notify_Show
; Return values .: Success - Returns 1
;                 Failure - Returns 0 and sets @error to 1 with @extended set to parameter index number
; Author ........: Melba23
; Example........; Yes
;=====================================================================================================================
Func _Notify_Set($vJust, $iCol = -1, $iBkCol = -1, $sFont_Name = "", $fSlide = False)

    ; Set parameters
    Switch $vJust
        Case Default
            For $i = 0 To 3
                $aNotify_Settings[1][$i] = $aNotify_Settings[0][$i]
            Next
            Return
        Case 0, 1, 2
            $aNotify_Settings[1][0] = $vJust
        Case Else
            Return SetError(1, 1, 0)
    EndSwitch

    Switch $iCol
        Case Default
            $aNotify_Settings[1][1] = $aNotify_Settings[0][1]
        Case 0 To 0xFFFFFF
            $aNotify_Settings[1][1] = $iCol
        Case -1
            ; Do nothing
        Case Else
            Return SetError(1, 2, 0)
    EndSwitch

    Switch $iBkCol
        Case Default
            $aNotify_Settings[1][2] = $aNotify_Settings[0][2]
        Case 0 To 0xFFFFFF
            $aNotify_Settings[1][2] = $iBkCol
        Case -1
            ; Do nothing
        Case Else
            Return SetError(1, 3, 0)
    EndSwitch

    Switch $sFont_Name
        Case Default
            $aNotify_Settings[1][3] = $aNotify_Settings[0][3]
        Case ""
            ; Do nothing
        Case Else
            If IsString($sFont_Name) Then
                $aNotify_Settings[1][3] = $sFont_Name
            Else
                Return SetError(1, 4, 0)
            EndIf
    EndSwitch

    If $fSlide = True Then
        $aNotify_Settings[0][4] = True
    Else
        $aNotify_Settings[0][4] = False
    EndIf

    Return 1

EndFunc   ;==>_Notify_Set

; #FUNCTION# =========================================================================================================
; Name...........: _Notify_Show
; Description ...: Shows a notification
; Syntax.........: _Notify_Show($vIcon, $sTitle, $sMessage, [$iDelay [, $iClick]])
; Parameters ....: $vIcon   - 0 - No icon, 8 - UAC, 16 - Stop, 32 - Query, 48 - Exclamation, 64 - Information
;                             The $MB_ICON constant can also be used for the last 4 above
;                             If set to the name of an exe, the main icon of that exe will be displayed
;                             If set to the name of an image file, that image will be displayed
;                             Any other value returns -1, error 1
;                 $sTitle   - Text to display as title in bold
;                 $sMessage - Text to display as message
;                             If $sTitle = "" then $sText can take 2 lines
;                 $iDelay   - The delay in seconds before the notification retracts (Default = 0 = Remains indefinitely)
;                 $iClick   - If notification will retact when clicked (Default = 1 = Clickable)
; Requirement(s).: v3.3.1.5 or higher - AdlibRegister/Unregister used in _Notify_Show
; Return values .: Success: Returns the handle of the Notification
;                  Failure: Returns -1 and sets @error as follows:
;                          1 = Maximum number of notification that can be displayed
;                          2 = Icon parameter invalid
;                          3 = StringSize error
;                          4 = Title/text will not fit in widest message (@extended = 0/1 = Title/Text)
;                          5 = Notification GUI creation failed
; Author ........: Melba23
; Notes .........;
; Example........; Yes
;=====================================================================================================================
Func _Notify_Show($vIcon, $sTitle, $sMessage, $iDelay = 0, $iClick = 1)

    If $aNotify_Data[0][0] = $aNotify_Data[0][1] Then
        Return SetError(1, 0, -1)
    EndIf

    Local $aLabel_Pos, $iLabel_Width, $iLabel_Height = 20

    ; Set default auto-sizing Notify dimensions
    Local $iNotify_Width_max = 300
    Local $iNotify_Width_min = 150
    Local $iNotify_Height = 40

    ; Check for icon
    Local $iIcon_Style = 0
    Local $iIcon_Reduction = 36
    Local $sDLL = "user32.dll"
    Local $sImg = ""
    If StringIsDigit($vIcon) Then
        Switch $vIcon
            Case 0
                $iIcon_Reduction = 0
            Case 8
                $sDLL = "imageres.dll"
                $iIcon_Style = 78
            Case 16 ; Stop
                $iIcon_Style = -4
            Case 32 ; Query
                $iIcon_Style = -3
            Case 48 ; Exclam
                $iIcon_Style = -2
            Case 64 ; Info
                $iIcon_Style = -5
            Case Else
                Return SetError(1, 0, -1)
        EndSwitch
    Else
        Switch StringLower(StringRight($vIcon, 3))
            Case "exe", "ico"
                $sDLL = $vIcon
                $iIcon_Style = 0
            Case "bmp", "jpg", "gif", "png"
                $sImg = $vIcon
        EndSwitch
    EndIf

    ; Determine max message width
    Local $iMax_Label_Width = $iNotify_Width_max - $iIcon_Reduction - 8

    ; Get text size
    If $sTitle Then
        ; Measure title
        $aLabel_Pos = _StringSize($sTitle, 9, Default, Default, $aNotify_Settings[1][3])
        If @error Then
            Return SetError(3, 0, -1)
        EndIf
        ; Check fits horizontally
        If $aLabel_Pos[2] > $iMax_Label_Width Then
            Return SetError(4, 0, -1)
        Else
            ; Set width required
            $iLabel_Width = $aLabel_Pos[2]
        EndIf
        ; Measure message
        $aLabel_Pos = _StringSize($sMessage, 9, Default, Default, $aNotify_Settings[1][3])
        If @error Then
            Return SetError(3, 0, -1)
        EndIf
        ; Check fits horizontally
        If $aLabel_Pos[2] > $iMax_Label_Width Then
            Return SetError(4, 1, -1)
        Else
            ; Adjust width required if needed
            If $aLabel_Pos[2] > $iLabel_Width Then
                $iLabel_Width = $aLabel_Pos[2]
            EndIf
        EndIf
    Else
        ; Measure message
        $aLabel_Pos = _StringSize($sMessage, 9, Default, Default, $aNotify_Settings[1][3], $iMax_Label_Width)
        If @error Then
            Return SetError(3, 0, -1)
        EndIf
        ; If wrapped check still fits vertically
        If $aLabel_Pos[3] > 40 Then
            Return SetError(4, 1, -1)
        EndIf
        ; Check fits horizontally
        If $aLabel_Pos[2] > $iMax_Label_Width Then
            Return SetError(4, 1, -1)
        Else
            ; Set Notification size and label position
            If $aLabel_Pos[2] > $iLabel_Width Then
                $iLabel_Width = $aLabel_Pos[2]
            EndIf
            $sMessage = $aLabel_Pos[0]
            ; Adjust vertical position to centre lines
            Local $iLabel_Y = Int((40 - $aLabel_Pos[3]) / 2)
        EndIf
    EndIf

    ; Set Notify size
    Local $iNotify_Width = $iLabel_Width + 8 + $iIcon_Reduction

    ; Increase if below min size
    If $iNotify_Width < $iNotify_Width_min + $iIcon_Reduction Then
        $iNotify_Width = $iNotify_Width_min + $iIcon_Reduction
        $iLabel_Width = $iNotify_Width_min - 8
    EndIf

    ; Set Notify coords depending on location
    Local $iNotify_X, $iNotify_Y
    Switch $aNotify_Data[0][4]
        Case 0 ; From bottom right
            $iNotify_X = $aNotify_Data[0][2] - $iNotify_Width
            $iNotify_Y = $aNotify_Data[0][3] - (50 * ($aNotify_Data[0][0] + 1))
        Case 1 ; From top right
            $iNotify_X = $aNotify_Data[0][2] - $iNotify_Width
            $iNotify_Y = $aNotify_Data[0][3] + (50 * ($aNotify_Data[0][0]))
        Case 2 ; From top left
            $iNotify_X = $aNotify_Data[0][2]
            $iNotify_Y = $aNotify_Data[0][3] + (50 * ($aNotify_Data[0][0]))
        Case 3 ; From bottom left
            $iNotify_X = $aNotify_Data[0][2]
            $iNotify_Y = $aNotify_Data[0][3] - (50 * ($aNotify_Data[0][0] + 1))
    EndSwitch

    ; Create Notify slice with $WS_POPUPWINDOW style and $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST and $WS_EX_STATICEDGE extended style
    Local $hNotify_Handle = GUICreate("", $iNotify_Width, $iNotify_Height, $iNotify_X, $iNotify_Y, 0x80880000, BitOR(0x00020000, 0x00000080, 0x00000008))
    If @error Then
        Return SetError(5, 0, -1)
    EndIf
    GUISetBkColor($aNotify_Settings[1][2])

    ; Create icon
    If $iIcon_Reduction Then
Switch StringLower(StringRight($sImg, 3))
Case "bmp", "jpg", "gif"
GUICtrlCreatePic($sImg, 4, 4, 32, 32)
Case "png"
_Show_PNG($sImg)
Case Else
GUICtrlCreateIcon($sDLL, $iIcon_Style, 4, 4)
        EndSwitch
    EndIf

    ; Create labels
    If $sTitle Then
        ; Title
        GUICtrlCreateLabel($sTitle, 4 + $iIcon_Reduction, 0, $iLabel_Width, $iLabel_Height)
        GUICtrlSetFont(-1, 9, 800, 0, $aNotify_Settings[1][3])
        GUICtrlSetBkColor(-1, $aNotify_Settings[1][2])
        GUICtrlSetColor(-1, $aNotify_Settings[1][1])
        GUICtrlSetStyle(-1, $aNotify_Settings[1][0])
        ; Message
        GUICtrlCreateLabel($sMessage, 4 + $iIcon_Reduction, 20, $iLabel_Width, $iLabel_Height)
        GUICtrlSetFont(-1, 9, 400, 0, $aNotify_Settings[1][3])
        GUICtrlSetBkColor(-1, $aNotify_Settings[1][2])
        GUICtrlSetColor(-1, $aNotify_Settings[1][1])
        GUICtrlSetStyle(-1, $aNotify_Settings[1][0])
    Else
        ; Message
        GUICtrlCreateLabel($sMessage, 4 + $iIcon_Reduction, $iLabel_Y, $iLabel_Width, 40 - $iLabel_Y)
        GUICtrlSetFont(-1, 9, 400, 0, $aNotify_Settings[1][3])
        GUICtrlSetBkColor(-1, $aNotify_Settings[1][2])
        GUICtrlSetColor(-1, $aNotify_Settings[1][1])
        GUICtrlSetStyle(-1, $aNotify_Settings[1][0])
    EndIf

    ; Slide Notify Slice into view and activate
    Switch $aNotify_Data[0][4]
        Case 0, 1
            DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $hNotify_Handle, "int", 1000, "long", 0x00040002) ; $AW_SLIDE_IN_RIGHT
        Case 2, 3
            DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $hNotify_Handle, "int", 1000, "long", 0x00040001) ; $AW_SLIDE_IN_LEFT
    EndSwitch

    ; Activate Notify without stealing focus
    GUISetState(@SW_SHOWNOACTIVATE, $hNotify_Handle)

    ; Store Notify data
    $aNotify_Data[0][0] += 1
    ReDim $aNotify_Data[$aNotify_Data[0][0] + 1][5]
    $aNotify_Data[$aNotify_Data[0][0]][0] = $hNotify_Handle
    $aNotify_Data[$aNotify_Data[0][0]][1] = $iDelay * 1000
    $aNotify_Data[$aNotify_Data[0][0]][2] = TimerInit()
    $aNotify_Data[$aNotify_Data[0][0]][3] = $iClick
    $aNotify_Data[$aNotify_Data[0][0]][4] = $iNotify_X

    ; Start Adlib function for Notify retraction
    If $aNotify_Data[0][0] = 1 Then
        AdlibRegister("_Notify_Timer", 1000)
    EndIf

Return $hNotify_Handle

EndFunc   ;==>_Notify_Show

; #FUNCTION# =========================================================================================================
; Name...........: _Notify_Hide
; Description ...: Hide a notification
; Syntax.........: _Notify_Show($hWnd)
; Parameters ....: None
; Requirement(s).: v3.3.1.5 or higher - AdlibRegister/Unregister used in _Notify_Show
; Return values .: Success: Returns 1
;                  Failure:  Returns 0 and sets @error as follows:
;                          1 = Invalid handle passed
;                          2 = Handle not found in Notification array
; Author ........: Melba23
; Notes .........;
; Example........; Yes
;=====================================================================================================================
Func _Notify_Hide($hWnd)

; Check for valid handle
If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)

; Look for handle in array
For $i = 1 To $aNotify_Data[0][0]
If $aNotify_Data[$i][0] = $hWnd Then
; If found then retract
_Notify_Delete($i)
_Notify_Reset($i)
Return 1
EndIf
Next

; Handle was not found
Return SetError(2, 0, 0)

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _Notify_RegMsg
; Description ...: Registers WM_MOUSEACTIVATE message needed for the UDF
; Syntax.........: _Notify_RegMsg()
; Parameters ....: None
; Requirement(s).: v3.3.1.5 or higher - AdlibRegister/Unregister used in _Notify_Show
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If another WM_MOUSEACTIVATE handler already registered, call the _Notify_WM_MOUSEACTIVATE handler
;                 function from within that handler
;                 If notifications not to retract when clicked the WM_MOUSEACTIVATE message need not be registered
; Example........: Yes
;=====================================================================================================================
Func _Notify_RegMsg()

    GUIRegisterMsg(0x0021, "_Notify_WM_MOUSEACTIVATE") ; $WM_MOUSEACTIVATE
    $aNotify_Data[0][4] = 1

EndFunc

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Notify_Timer
; Description ...: Checks whether a notification has timed out
; Syntax ........: _Notify_Timer()
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _Notify_Timer()

    If $aNotify_Settings[1][5] Then
        Return
    EndIf

    If $aNotify_Settings[0][5] Then
        Return
    EndIf

    ; Set Prevent simultaneous click
    $aNotify_Settings[0][5] = True

    ; Pause Adlib as retraction and movement could overrun delay time
    AdlibUnRegister("_Notify_Timer")

    Local $fMoved = False

    ; Run through notifications
    For $i = $aNotify_Data[0][0] To 1 Step -1
        ; Check timer if needed
        If $aNotify_Data[$i][1] And TimerDiff($aNotify_Data[$i][2]) > $aNotify_Data[$i][1] Then
            _Notify_Delete($i)
            $fMoved = True
            ExitLoop
        EndIf
    Next

    ; Adjust positions of Notifications
    If $fMoved Then
        _Notify_Reset($i)
    EndIf

    ; Restart Adlib if needed
    If $aNotify_Data[0][0] Then
        AdlibRegister("_Notify_Timer", 1000)
    EndIf
    ; Re-enable clicks
    $aNotify_Settings[0][5] = False

EndFunc   ;==>_Notify_Timer

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Notify_WM_MOUSEACTIVATE
; Description ...: Message handler to check if notification clicked
; Syntax ........: _Notify_WM_MOUSEACTIVATE($hWnd, $Msg, $wParam, $lParam)
; Parameters ....: Standard message handler parameters
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _Notify_WM_MOUSEACTIVATE($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam, $lParam

    ; Check timer is not checking
    If $aNotify_Settings[0][5] Then
        Return
    EndIf
    ; Check handler not already retracting
    If $aNotify_Settings[1][5] Then
        Return
    EndIf
    ; Set flag to show handler retracting
    $aNotify_Settings[1][5] = True

    ; Declare flag
    Local $fMoved = False

    For $i = $aNotify_Data[0][0] To 1 Step -1
        If $aNotify_Data[$i][3] And $hWnd = $aNotify_Data[$i][0] Then
            _Notify_Delete($i)
            $fMoved = True
            ExitLoop
        EndIf
    Next

    ; Adjust positions of Notifications
    If $fMoved Then
        _Notify_Reset($i)
    EndIf

    ; Clear Running flag
    $aNotify_Settings[1][5] = False

    Return "GUI_RUNDEFMSG"

EndFunc   ;==>_Notify_WM_MOUSEACTIVATE

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Notify_Delete
; Description ...: Retract a notification when timed out or clicked
; Syntax ........: _Notify_Delete($i)
; Parameters ....: $i - Index of notification to be retracted
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _Notify_Delete($i)

    ; Retract and delete notification
    Switch $aNotify_Data[0][4]
        Case 0, 1
            DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $aNotify_Data[$i][0], "int", 500, "long", 0x00050001) ; $AW_SLIDE_OUT_RIGHT
        Case 2, 3
            DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $aNotify_Data[$i][0], "int", 500, "long", 0x00050002) ; $AW_SLIDE_OUT_LEFT
    EndSwitch
    GUIDelete($aNotify_Data[$i][0])
    ; Adjust array
    For $j = $i + 1 To $aNotify_Data[0][0]
        For $k = 0 To 4
            $aNotify_Data[$j - 1][$k] = $aNotify_Data[$j][$k]
        Next
    Next
    ReDim $aNotify_Data[$aNotify_Data[0][0]][5]
    $aNotify_Data[0][0] -= 1

EndFunc

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Notify_Reset
; Description ...: Reposition remaining notifications on screen
; Syntax ........: _Notify_Reset($i)
; Parameters ....: $i - Index of notification just retracted
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _Notify_Reset($iIndex)

    If $aNotify_Settings[0][4] Then
        ; Set step size depending on number of notifications to move
        Local $iStep = 1 + Int(($aNotify_Data[0][0] - $iIndex) / 3)
        ; Slide notifications into new positions depending on location
        Switch $aNotify_Data[0][4]
            Case 0, 3
                For $j = 1 To 50 Step $iStep
                    For $i = $iIndex To $aNotify_Data[0][0]
                        WinMove($aNotify_Data[$i][0], "", $aNotify_Data[$i][4], $aNotify_Data[0][3] - (50 * ($i + 1)) + $j)
                    Next
                Next
            Case 1, 2
                For $j = 1 To 50 Step $iStep
                    For $i = $iIndex To $aNotify_Data[0][0]
                        WinMove($aNotify_Data[$i][0], "", $aNotify_Data[$i][4], $aNotify_Data[0][3] + (50 * $i) - $j)
                    Next
                Next
        EndSwitch
    Else
        ; Move notifications into new positions instantly depending on location
        Switch $aNotify_Data[0][4]
            Case 0, 3
                For $i = 1 To $aNotify_Data[0][0]
                    WinMove($aNotify_Data[$i][0], "", $aNotify_Data[$i][4], $aNotify_Data[0][3] - (50 * $i))
                Next
            Case 1, 2
                For $i = 1 To $aNotify_Data[0][0]
                    WinMove($aNotify_Data[$i][0], "", $aNotify_Data[$i][4], $aNotify_Data[0][3] + (50 * ($i - 1)))
                Next
        EndSwitch
    EndIf

EndFunc

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Notify_GetDefFont
; Description ...: Determine system default MsgBox font
; Syntax ........: _Notify_GetDefFont()
; Parameters ....: None
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _Notify_GetDefFont()

    ; Get default system font data
    Local $tNONCLIENTMETRICS = DllStructCreate("uint;int;int;int;int;int;byte[60];int;int;byte[60];int;int;byte[60];byte[60];byte[60]")
    DllStructSetData($tNONCLIENTMETRICS, 1, DllStructGetSize($tNONCLIENTMETRICS))
    DllCall("user32.dll", "int", "SystemParametersInfo", "int", 41, "int", DllStructGetSize($tNONCLIENTMETRICS), "ptr", DllStructGetPtr($tNONCLIENTMETRICS), "int", 0)
    ; Read font data for MsgBox font
    Local $tLOGFONT = DllStructCreate("long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;char[32]", DllStructGetPtr($tNONCLIENTMETRICS, 15))
    ; Font name
    Return DllStructGetData($tLOGFONT, 14)

EndFunc   ;==>_Notify_GetDefFont

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Show_PNG
; Description ...: Set PNG as image
; Syntax ........: _Show_PNG($sImg)
; Parameters ....: $sImg - Path of image file
; Author ........: UEZ
; Modified.......: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _Show_PNG($sImg)

_GDIPlus_Startup()
Local $hPic = GUICtrlCreatePic("", 4, 4, 32, 32)
Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sImg)
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", 32, "int", 32, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0)
Local $hBitmap_Resized = $aResult[6]
Local $hBMP_Ctxt = _GDIPlus_ImageGetGraphicsContext($hBitmap_Resized)
DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hBMP_Ctxt, "int", 7)
_GDIPlus_GraphicsDrawImageRect($hBMP_Ctxt , $hBitmap, 0, 0, 32, 32)
Local $hHBitmap = _BitmapCreateDIB($hBitmap_Resized)
_WinAPI_DeleteObject(GUICtrlSendMsg($hPic, 0x0172, 0, $hHBitmap))
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_BitmapDispose($hBitmap_Resized)
_GDIPlus_GraphicsDispose($hBMP_Ctxt)
_WinAPI_DeleteObject($hHBitmap)
_GDIPlus_Shutdown()

EndFunc

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _BitmapCreateDIB
; Description ...: Create bitmap
; Syntax ........: _BitmapCreateDIB($hBitmap)
; Parameters ....: $hBitmap - Handle of bitmap
; Author ........: UEZ
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _BitmapCreateDIB($hBitmap)

Local $hRet = 0

    Local $aRet1 = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "ptr", $hBitmap, "float*", 0, "float*", 0)
    If (@error) Or ($aRet1[0]) Then Return 0
    Local $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $aRet1[2], $aRet1[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    Local $pBits = DllStructGetData($tData, "Scan0")
    If Not $pBits Then Return 0
    Local $tBIHDR = DllStructCreate("dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword")
    DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))
    DllStructSetData($tBIHDR, 2, $aRet1[2])
    DllStructSetData($tBIHDR, 3, $aRet1[3])
    DllStructSetData($tBIHDR, 4, 1)
    DllStructSetData($tBIHDR, 5, 32)
    DllStructSetData($tBIHDR, 6, 0)
    Local $aRet2 = DllCall("gdi32.dll", "ptr", "CreateDIBSection", "hwnd", 0, "ptr", DllStructGetPtr($tBIHDR), "uint", 0, "ptr*", 0, "ptr", 0, "dword", 0)
    If (Not @error) And ($aRet2[0]) Then
        DllCall("gdi32.dll", "dword", "SetBitmapBits", "ptr", $aRet2[0], "dword", $aRet1[2] * $aRet1[3] * 4, "ptr", DllStructGetData($tData, "Scan0"))
        $hRet = $aRet2[0]
    EndIf
    _GDIPlus_BitmapUnlockBits($hBitmap, $tData)
    Return $hRet
EndFunc   ;==>_BitmapCreateDIB

StringSize UDF Needed for Melba23's Notify UDF:

#include-once

; #INDEX# ============================================================================================================
; Title .........: _StringSize
; AutoIt Version : v3.2.12.1 or higher
; Language ......: English
; Description ...: Returns size of rectangle required to display string - maximum width can be chosen
; Remarks .......:
; Note ..........:
; Author(s) .....:  Melba23 - thanks to trancexx for the default DC code
; ====================================================================================================================

;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

; #CURRENT# ==========================================================================================================
; _StringSize: Returns size of rectangle required to display string - maximum width can be chosen
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _StringSize_Error_Close: Releases DC and deletes font object after error
; _StringSize_DefaultFontName: Determines Windows default font
; ====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _StringSize
; Description ...: Returns size of rectangle required to display string - maximum permitted width can be chosen
; Syntax ........: _StringSize($sText[, $iSize[, $iWeight[, $iAttrib[, $sName[, $iWidth[, $hWnd]]]]]])
; Parameters ....: $sText   - String to display
;                  $iSize   - [optional] Font size in points - (default = 8.5)
;                  $iWeight - [optional] Font weight - (default = 400 = normal)
;                  $iAttrib - [optional] Font attribute (0-Normal (default), 2-Italic, 4-Underline, 8 Strike)
;                             + 1 if tabs are to be expanded before sizing
;                  $sName   - [optional] Font name - (default = Tahoma)
;                  $iWidth  - [optional] Max width for rectangle - (default = 0 => width of original string)
;                  $hWnd    - [optional] GUI in which string will be displayed - (default 0 => normally not required)
; Requirement(s) : v3.2.12.1 or higher
; Return values .: Success - Returns 4-element array: ($iWidth set // $iWidth not set)
;                  |$array[0] = String reformatted with additonal @CRLF // Original string
;                  |$array[1] = Height of single line in selected font // idem
;                  |$array[2] = Width of rectangle required for reformatted // original string
;                  |$array[3] = Height of rectangle required for reformatted // original string
;                  Failure - Returns 0 and sets @error:
;                  |1 - Incorrect parameter type (@extended = parameter index)
;                  |2 - DLL call error - extended set as follows:
;                       |1 - GetDC failure
;                       |2 - SendMessage failure
;                       |3 - GetDeviceCaps failure
;                       |4 - CreateFont failure
;                       |5 - SelectObject failure
;                       |6 - GetTextExtentPoint32 failure
;                  |3 - Font too large for chosen max width - a word will not fit
; Author ........: Melba23 - thanks to trancexx for the default DC code
; Modified ......:
; Remarks .......: The use of the $hWnd parameter is not normally necessary - it is only required if the UDF does not
;                   return correct dimensions without it.
; Related .......:
; Link ..........:
; Example .......: Yes
;=====================================================================================================================
Func _StringSize($sText, $iSize = 8.5, $iWeight = 400, $iAttrib = 0, $sName = "", $iMaxWidth = 0, $hWnd = 0)

; Set parameters passed as Default
If $iSize = Default Then $iSize = 8.5
If $iWeight = Default Then $iWeight = 400
If $iAttrib = Default Then $iAttrib = 0
If $sName = "" Or $sName = Default Then $sName = _StringSize_DefaultFontName()

; Check parameters are correct type
If Not IsString($sText) Then Return SetError(1, 1, 0)
If Not IsNumber($iSize) Then Return SetError(1, 2, 0)
If Not IsInt($iWeight) Then Return SetError(1, 3, 0)
If Not IsInt($iAttrib) Then Return SetError(1, 4, 0)
If Not IsString($sName) Then Return SetError(1, 5, 0)
If Not IsNumber($iMaxWidth) Then Return SetError(1, 6, 0)
If Not IsHwnd($hWnd) And $hWnd <> 0 Then Return SetError(1, 7, 0)

Local $aRet, $hDC, $hFont, $hLabel = 0, $hLabel_Handle

; Check for tab expansion flag
Local $iExpTab = BitAnd($iAttrib, 1)
; Remove possible tab expansion flag from font attribute value
$iAttrib = BitAnd($iAttrib, BitNot(1))

; If GUI handle was passed
If IsHWnd($hWnd) Then
; Create label outside GUI borders
$hLabel = GUICtrlCreateLabel("", -10, -10, 10, 10)
$hLabel_Handle = GUICtrlGetHandle(-1)
GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sName)
; Create DC
$aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hLabel_Handle)
If @error Or $aRet[0] = 0 Then
GUICtrlDelete($hLabel)
Return SetError(2, 1, 0)
EndIf
$hDC = $aRet[0]
$aRet = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hLabel_Handle, "int", 0x0031, "wparam", 0, "lparam", 0) ; $WM_GetFont
If @error Or $aRet[0] = 0 Then
GUICtrlDelete($hLabel)
Return SetError(2, _StringSize_Error_Close(2, $hDC), 0)
EndIf
$hFont = $aRet[0]
Else
; Get default DC
$aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hWnd)
If @error Or $aRet[0] = 0 Then Return SetError(2, 1, 0)
$hDC = $aRet[0]
; Create required font
$aRet = DllCall("gdi32.dll", "int", "GetDeviceCaps", "handle", $hDC, "int", 90) ; $LOGPIXELSY
If @error Or $aRet[0] = 0 Then Return SetError(2, _StringSize_Error_Close(3, $hDC), 0)
Local $iInfo = $aRet[0]
$aRet = DllCall("gdi32.dll", "handle", "CreateFontW", "int", -$iInfo * $iSize / 72, "int", 0, "int", 0, "int", 0, _
"int", $iWeight, "dword", BitAND($iAttrib, 2), "dword", BitAND($iAttrib, 4), "dword", BitAND($iAttrib, 8), "dword", 0, "dword", 0, _
"dword", 0, "dword", 5, "dword", 0, "wstr", $sName)
If @error Or $aRet[0] = 0 Then Return SetError(2, _StringSize_Error_Close(4, $hDC), 0)
$hFont = $aRet[0]
EndIf

; Select font and store previous font
$aRet = DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hFont)
If @error Or $aRet[0] = 0 Then Return SetError(2, _StringSize_Error_Close(5, $hDC, $hFont, $hLabel), 0)
Local $hPrevFont = $aRet[0]

; Declare variables
    Local $avSize_Info[4], $iLine_Length, $iLine_Height = 0, $iLine_Count = 0, $iLine_Width = 0, $iWrap_Count, $iLast_Word, $sTest_Line
; Declare and fill Size structure
Local $tSize = DllStructCreate("int X;int Y")
DllStructSetData($tSize, "X", 0)
DllStructSetData($tSize, "Y", 0)

; Ensure EoL is @CRLF and break text into lines
$sText = StringRegExpReplace($sText, "((?<!x0d)x0a|x0d(?!x0a))", @CRLF)
Local $asLines = StringSplit($sText, @CRLF, 1)

; For each line
For $i = 1 To $asLines[0]
; Expand tabs if required
If $iExpTab Then
$asLines[$i] = StringReplace($asLines[$i], @TAB, " XXXXXXXX")
EndIf
; Size line
$iLine_Length = StringLen($asLines[$i])
DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $asLines[$i], "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0)
If DllStructGetData($tSize, "X") > $iLine_Width Then $iLine_Width = DllStructGetData($tSize, "X")
If DllStructGetData($tSize, "Y") > $iLine_Height Then $iLine_Height = DllStructGetData($tSize, "Y")
Next

; Check if $iMaxWidth has been both set and exceeded
If $iMaxWidth <> 0 And $iLine_Width > $iMaxWidth Then ; Wrapping required
; For each Line
For $j = 1 To $asLines[0]
; Size line unwrapped
$iLine_Length = StringLen($asLines[$j])
DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $asLines[$j], "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0)
; Check wrap status
If DllStructGetData($tSize, "X") < $iMaxWidth - 4 Then
; No wrap needed so count line and store
$iLine_Count += 1
$avSize_Info[0] &= $asLines[$j] & @CRLF
Else
; Wrap needed so zero counter for wrapped lines
$iWrap_Count = 0
; Build line to max width
While 1
; Zero line width
$iLine_Width = 0
; Initialise pointer for end of word
$iLast_Word = 0
; Add characters until EOL or maximum width reached
For $i = 1 To StringLen($asLines[$j])
; Is this just past a word ending?
If StringMid($asLines[$j], $i, 1) = " " Then $iLast_Word = $i - 1
; Increase line by one character
$sTest_Line = StringMid($asLines[$j], 1, $i)
; Get line length
$iLine_Length = StringLen($sTest_Line)
DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sTest_Line, "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0)
$iLine_Width = DllStructGetData($tSize, "X")
; If too long exit the loop
If $iLine_Width >= $iMaxWidth - 4 Then ExitLoop
Next
; End of the line of text?
If $i > StringLen($asLines[$j]) Then
; Yes, so add final line to count
$iWrap_Count += 1
; Store line
$avSize_Info[0] &= $sTest_Line & @CRLF
ExitLoop
Else
; No, but add line just completed to count
$iWrap_Count += 1
; Check at least 1 word completed or return error
If $iLast_Word = 0 Then Return SetError(3, _StringSize_Error_Close(0, $hDC, $hFont, $hLabel), 0)
; Store line up to end of last word
$avSize_Info[0] &= StringLeft($sTest_Line, $iLast_Word) & @CRLF
; Strip string to point reached
$asLines[$j] = StringTrimLeft($asLines[$j], $iLast_Word)
; Trim leading whitespace
$asLines[$j] = StringStripWS($asLines[$j], 1)
; Repeat with remaining characters in line
EndIf
WEnd
; Add the number of wrapped lines to the count
$iLine_Count += $iWrap_Count
EndIf
Next
; Reset any tab expansions
If $iExpTab Then
$avSize_Info[0] = StringRegExpReplace($avSize_Info[0], "x20?XXXXXXXX", @TAB)
EndIf
; Complete return array
$avSize_Info[1] = $iLine_Height
$avSize_Info[2] = $iMaxWidth
; Convert lines to pixels and add drop margin
$avSize_Info[3] = ($iLine_Count * $iLine_Height) + 4
Else ; No wrapping required
; Create return array (add drop margin to height)
Local $avSize_Info[4] = [$sText, $iLine_Height, $iLine_Width, ($asLines[0] * $iLine_Height) + 4]
EndIf

; Clear up
    DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hPrevFont)
DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont)
DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
If $hLabel Then GUICtrlDelete($hLabel)

Return $avSize_Info

EndFunc ;==>_StringSize

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _StringSize_Error_Close
; Description ...: Releases DC and deleted font object if required after error
; Syntax ........: _StringSize_Error_Close ($iExtCode, $hDC, $hGUI)
; Parameters ....: $iExtCode   - code to return
;                  $hDC, $hGUI - handles as set in _StringSize function
; Return value ..: $iExtCode as passed
; Author ........: Melba23
; Modified.......:
; Remarks .......: This function is used internally by _StringSize
; ===============================================================================================================================
Func _StringSize_Error_Close($iExtCode, $hDC = 0, $hFont = 0, $hLabel = 0)

If $hFont <> 0 Then DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont)
If $hDC <> 0 Then DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
If $hLabel Then GUICtrlDelete($hLabel)

Return $iExtCode

EndFunc ;=>_StringSize_Error_Close

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _StringSize_DefaultFontName
; Description ...: Determines Windows default font
; Syntax ........: _StringSize_DefaultFontName()
; Parameters ....: None
; Return values .: Success - Returns name of system default font
;                  Failure - Returns "Tahoma"
; Author ........: Melba23, based on some original code by Larrydalooza
; Modified.......:
; Remarks .......: This function is used internally by _StringSize
; ===============================================================================================================================
Func _StringSize_DefaultFontName()

; Get default system font data
Local $tNONCLIENTMETRICS = DllStructCreate("uint;int;int;int;int;int;byte[60];int;int;byte[60];int;int;byte[60];byte[60];byte[60]")
DLLStructSetData($tNONCLIENTMETRICS, 1, DllStructGetSize($tNONCLIENTMETRICS))
DLLCall("user32.dll", "int", "SystemParametersInfo", "int", 41, "int", DllStructGetSize($tNONCLIENTMETRICS), "ptr", DllStructGetPtr($tNONCLIENTMETRICS), "int", 0)
Local $tLOGFONT = DllStructCreate("long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;char[32]", DLLStructGetPtr($tNONCLIENTMETRICS, 13))
If IsString(DllStructGetData($tLOGFONT, 14)) Then
Return DllStructGetData($tLOGFONT, 14)
Else
Return "Tahoma"
EndIf

EndFunc ;=>_StringSize_DefaultFontName

CheckGmail UDF:

; #FUNCTION# ====================================================================================================================
; Name ..........: _CheckMail
; Description ...: Checks a Google Email for new emails.
; Syntax ........: _CheckMail($UserName, $Pswd[, $UserAgentString = ""])
; Parameters ....: $UserName            - An unknown value.
;                 $Pswd             - An unknown value.
;                 $UserAgentString   - [optional] An unknown value. Default is "".
; Return values .: A 2d array with email information as follows~
;                   1|Title
;                   2|Name
;                   3|Email
;                   4|Summary
;                   5|Date
;                   6|Time
;
; Author ........: dantay9
; Modified ......: THAT1ANONYMOUSDUDE
; Remarks .......:
; Related .......:
; Link ..........: http://www.autoitscript.com/forum/topic/...-checker/page__view__findpost_
; Example .......: Yes
; ===============================================================================================================================
Func _CheckMail($UserName, $Pswd, $UserAgentString = "")
    If Not $UserName Then Return SetError(2,0,0)
    If Not $Pswd Then Return SetError(3,0,0)
    If $UserAgentString Then HttpSetUserAgent($UserAgentString)
    Local $source = InetRead("https://" & $UserName & ":" & $Pswd & "@gmail.google.com/gmail/feed/atom",1)
    If @error Then
        ConsoleWrite("!>Error Getting URL Source!" & @CR & "     404>@Error =" & @error & @CR & "    404>@Extended =" & @extended & @CR)
        Return SetError(4,0,0)
    EndIf
    If $source Then
        $source = BinaryToString($source)
    Else
        Return SetError(5,0,0)
    EndIf
    If StringLeft(StringStripWS($source, 8), 46) == "<HTML><HEAD><TITLE>Unauthorized</TITLE></HEAD>" Then  Return SetError(6, 0, 0)
    If Not Number(StringBetween($source, "<fullcount>", "</fullcount>")) Then Return SetError(0,0,0)
$EmailCount = StringBetween($source, "<fullcount>", "</fullcount>")
    Local $Email = _StringBetween($source, "<entry>", "</entry>")
    If @error Then Return SetError(1, 0, 0)
    Local $Time
    $Count = UBound($Email)
    Local $Datum[$Count + 1][6]
    $Datum[0][0] = StringBetween($source, "<title>", "</title>")
    $Datum[0][1] = StringBetween($source, "<tagline>", "</tagline>")
    For $i = 0 To $Count - 1
        $Datum[$i+1][0] = StringBetween($Email[$i], "<title>", "</title>")
        If Not $Datum[$i+1][0] Then $Datum[$i][0] = "(no subject)"
        $Datum[$i+1][1] = StringBetween($Email[$i], "<name>", "</name>")
        $Datum[$i+1][2] = StringBetween($Email[$i], "<email>", "</email>")
        $Datum[$i+1][3] = StringBetween($Email[$i], "<summary>", "</summary>")
        $Time = StringBetween($Email[$i], "<issued>", "</issued>")
        $Datum[$i+1][4] = DateFromTimeDate($Time)
        $Datum[$i+1][5] = TimeFromTimeDate($Time)
    Next
    Return SetError(0,$Count,$Datum)
EndFunc
Func StringBetween($Str, $S, $E)
    Local $B = _StringBetween($Str, $S, $E)
    If @error Then Return SetError(1,0,0)
    Return SetError(0,0,$B[0])
EndFunc   ;==>StringBetween

; #FUNCTION# ====================================================================================================================
; Name ..........: DateFromTimeDate
; Description ...: Returns email sent date.
; Syntax ........: DateFromTimeDate($String)
; Parameters ....: $String            - A gmail date string
; Return values .: None
; Author ........: ???
; Example .......: No
; ===============================================================================================================================

Func DateFromTimeDate($String)
    Local $RegEx = StringRegExp($String, "(?<Year>d{2}|d{4})(?:-)(?<Month>d{1,2})(?:-)(?<Day>d{1,2})", 1)
    If IsArray($RegEx) Then
        Return Int($RegEx[0]) & "/" & Int($RegEx[1]) & "/" & Int($RegEx[2])
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>DateFromTimeDate

; #FUNCTION# ====================================================================================================================

; Name ..........: TimeFromTimeDate
; Description ...: Returns the email sent time.
; Syntax ........: TimeFromTimeDate($String)
; Parameters ....: $String            - An unknown value.
; Return values .: None
; Author ........: ???
; Example .......: No
; ===============================================================================================================================

Func TimeFromTimeDate($String)
    Local $RegEx = StringRegExp($String, "(?<Hour>d{1,2})(?::)(?<Minute>d{1,2})(?::)(?<Second>d{1,2})", 1)
    If IsArray($RegEx) Then
        Return (Int($RegEx[0]) - 4) & ":" & Int($RegEx[1]) & ":" & Int($RegEx[2]) ;don't know why I have to subtract 4
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>TimeFromTimeDate
Link to comment
Share on other sites

I don't think I understand what's going on really.

#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=..Downloadsgmail.ico
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#Obfuscator_Parameters=/so
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <string.au3>
#include "Notify.au3"
#include <array.au3>
Global $eReturn
Global $Count
Global $User = "marlboroloco"
Global $Pass = "astronomicamente"
_Display()
_Notify_RegMsg()
_Notify_Locate(0)
AdlibRegister("_Display", 5000)
_Notify_Set(Default)
While 1
    Sleep(100)
WEnd
Func _Display()
    AdlibUnRegister("_Display")
    $eReturn = _CheckMail($User, $Pass)
    Switch @error
        Case 0
            Switch @extended
                Case True
                    $Count = UBound($eReturn) - 1
                    For $x = 0 To $Count
                        _Notify_Show(@AutoItExe, "", $eReturn[$x][1] & @CR & $eReturn[$x][0])
                        Switch @error
                            Case 4
                                MsgBox(16,"text error!","Maximum text legth breached!")
                        EndSelect
                    Next
                Case False
                    ;
            EndSwitch
        Case 1
            MsgBox(0, "Error!", "Couldn't get your new emails for some reason...")
            Exit
        Case 2, 3
            MsgBox(0, "Error!", "you need to enter an user name and password!")
            Exit
        Case 4
            MsgBox(16, "Error!", "Error Getting URL Source!")
            Exit
        Case 5
            MsgBox(16, "Error!", "No response?")
            Exit
        Case 6
            MsgBox(16, "Error!", "Unauthorized access, possibly a wrong username or password!")
            Exit
    EndSwitch
    Return AdlibRegister("_Display", 5000)
EndFunc   ;==>_Display
; #FUNCTION# ====================================================================================================================
; Name ..........: _CheckMail
; Description ...: Checks a Google Email for new emails.
; Syntax ........: _CheckMail($UserName, $Pswd[, $UserAgentString = ""])
; Parameters ....: $UserName            - An unknown value.
;                $Pswd           - An unknown value.
;                $UserAgentString   - [optional] An unknown value. Default is "".
; Return values .: A 2d array with email information as follows~
;                  1|Title
;                  2|Name
;                  3|Email
;                  4|Summary
;                  5|Date
;                  6|Time
;
; Author ........: dantay9
; Modified ......: THAT1ANONYMOUSDUDE
; Remarks .......:
; Related .......:
; Link ..........: http://www.autoitscript.com/forum/topic/...-checker/page__view__findpost_
; Example .......: Yes
; ===============================================================================================================================
Func _CheckMail($UserName, $Pswd, $UserAgentString = "")
    If Not $UserName Then Return SetError(2,0,0)
    If Not $Pswd Then Return SetError(3,0,0)
    If $UserAgentString Then HttpSetUserAgent($UserAgentString)
    Local $source = InetRead("https://" & $UserName & ":" & $Pswd & "@gmail.google.com/gmail/feed/atom",1)
    If @error Then
        ConsoleWrite("!>Error Getting URL Source!" & @CR & "     404>@Error =" & @error & @CR & "    404>@Extended =" & @extended & @CR)
        Return SetError(4,0,0)
    EndIf
    If $source Then
        $source = BinaryToString($source)
    Else
        Return SetError(5,0,0)
    EndIf
    If StringLeft(StringStripWS($source, 8), 46) == "<HTML><HEAD><TITLE>Unauthorized</TITLE></HEAD>" Then  Return SetError(6, 0, 0)
    If Not Number(StringBetween($source, "<fullcount>", "</fullcount>")) Then Return SetError(0,0,0)
    Local $EmailCount = StringBetween($source, "<fullcount>", "</fullcount>")
    Local $Email = _StringBetween($source, "<entry>", "</entry>")
    If @error Then Return SetError(1, 0, 0)
    Local $Time
    Local $Datum[$EmailCount][6]
    $Datum[0][0] = StringBetween($source, "<title>", "</title>")
    $Datum[0][1] = StringBetween($source, "<tagline>", "</tagline>")
    For $i = 0 To $EmailCount - 1
        $Datum[$i][0] = StringBetween($Email[$i], "<title>", "</title>")
        If Not $Datum[$i][0] Then $Datum[$i][0] = "(no subject)"
        $Datum[$i][1] = StringBetween($Email[$i], "<name>", "</name>")
        $Datum[$i][2] = StringBetween($Email[$i], "<email>", "</email>")
        $Datum[$i][3] = StringBetween($Email[$i], "<summary>", "</summary>")
        $Time = StringBetween($Email[$i], "<issued>", "</issued>")
        $Datum[$i][4] = DateFromTimeDate($Time)
        $Datum[$i][5] = TimeFromTimeDate($Time)
    Next
    Return SetError(0,$EmailCount,$Datum)
EndFunc
Func StringBetween($Str, $S, $E)
    Local $B = _StringBetween($Str, $S, $E)
    If @error Then Return SetError(1,0,0)
    Return SetError(0,0,$B[0])
EndFunc   ;==>StringBetween
; #FUNCTION# ====================================================================================================================
; Name ..........: DateFromTimeDate
; Description ...: Returns email sent date.
; Syntax ........: DateFromTimeDate($String)
; Parameters ....: $String          - A gmail date string
; Return values .: None
; Author ........: ???
; Example .......: No
; ===============================================================================================================================
Func DateFromTimeDate($String)
    Local $RegEx = StringRegExp($String, "(?<Year>d{2}|d{4})(?:-)(?<Month>d{1,2})(?:-)(?<Day>d{1,2})", 1)
    If IsArray($RegEx) Then
        Return Int($RegEx[0]) & "/" & Int($RegEx[1]) & "/" & Int($RegEx[2])
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>DateFromTimeDate
; #FUNCTION# ====================================================================================================================
; Name ..........: TimeFromTimeDate
; Description ...: Returns the email sent time.
; Syntax ........: TimeFromTimeDate($String)
; Parameters ....: $String          - An unknown value.
; Return values .: None
; Author ........: ???
; Example .......: No
; ===============================================================================================================================
Func TimeFromTimeDate($String)
    Local $RegEx = StringRegExp($String, "(?<Hour>d{1,2})(?::)(?<Minute>d{1,2})(?::)(?<Second>d{1,2})", 1)
    If IsArray($RegEx) Then
        Return (Int($RegEx[0]) - 4) & ":" & Int($RegEx[1]) & ":" & Int($RegEx[2]) ;don't know why I have to subtract 4
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>TimeFromTimeDate
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...