Announcement

Collapse
No announcement yet.

Calling mailto: crashes program

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Calling mailto: crashes program

    Hi all,
    I have another 'mailto:' problem.
    When I call the mailto: program (is it actually a program??) from within
    my PB/DLL routine and the body of the mail (the actual messagetext) is
    too long my program crashes...
    I have included a demo where you can test the problem. You can enter the length
    of the message.
    When you enter a number well below 1000, all behaves normally: my e-mail program (Eudora 5.0)
    starts up and a new mail is prepared with all items nicely filled in (subject, body, etc).
    When my message is around 2000 characters long, nothing happens.. My PB routine does not
    crash but my e-mail program doesn't seem to receive anything.
    When the message length is 3000 bytes or more, my PB program immediately crashes...
    I run this on Win2k.
    Could it be a stack problem?
    I just tested it on Outlook Express and the problem remains the same...
    Kind regards
    Eddy
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "C:\PBDLL60\Winapi\Win32api.inc"
    #INCLUDE "C:\PBDLL60\Winapi\Commctrl.inc"
    %IDINPOK       = 100
    %IDINPCANCEL   = 102
    %IDINPTEXT     = 120
    %IDINPPROMPT  = 121
    
    GLOBAL inputtext AS STRING
    GLOBAL hDlg   AS LONG
    GLOBAL result AS LONG
    
    DECLARE CALLBACK FUNCTION OkButton()
    DECLARE CALLBACK FUNCTION CancelButton()
    DECLARE FUNCTION SendAsMail(mStr AS STRING) AS LONG
    
    FUNCTION PBMAIN() AS LONG
      DIALOG NEW 0, "Mailto: problem", ,, 260, 70, 0, 0 TO hDlg
      CONTROL ADD LABEL, hDlg, %IDINPPROMPT, "< 1000: no problem, 2000: does nothing, >3000: crash", 5,  12, 200, 12, 0
      CONTROL ADD TEXTBOX, hDlg, %IDINPTEXT, "100", 5,  24, 240, 12, 0
      CONTROL ADD BUTTON, hDlg, %IDINPOK, "Send", 34, 45, 40, 14, &H1&  CALL OkButton
      CONTROL ADD BUTTON, hDlg, %IDINPCANCEL, "Exit", 84, 45, 40, 14, 0 CALL CancelButton
      DIALOG SHOW MODAL hDlg TO result
    END FUNCTION
    
    CALLBACK FUNCTION OkButton()
      LOCAL result AS LONG
      CONTROL GET TEXT CBHNDL, %IDINPTEXT TO inputtext
      result = SendAsMail(REPEAT$(VAL(inputtext),"a" ))
    END FUNCTION
    
    CALLBACK FUNCTION CancelButton()
      DIALOG END CBHNDL, 0
    END FUNCTION
    
    FUNCTION SendAsMail(mStr AS STRING) AS LONG
       LOCAL mLen AS LONG', mText AS STRING
       LOCAL mText AS ASCIIZ * 50000
       mLen = LEN(mStr)
       IF mLen > 1 THEN
          'REPLACE CHR$(13,10) WITH "%0d%0a" IN mStr    'Proper linefeed for mail
          REPLACE CHR$(32) WITH "%20" IN mStr          'Spaces
          REPLACE CHR$(38) WITH "%26" IN mStr          '&
          REPLACE CHR$(10) WITH "%0a" IN mStr          'char$(10)
          REPLACE CHR$(13) WITH "%0d" IN mStr          'char$(13)
          REPLACE CHR$(9)  WITH "%09" IN mStr          'char$(9)
       END IF
       mText = "mailto:" & "[email protected]" & "?"
       mText = mText & "Subject=" & "Some subject"
       mText = mText & "&Body="   & mStr
       'FUNCTION = ShellExecute(hMain, "open", BYVAL STRPTR(mText), "", "", %SW_SHOWNORMAL)
       FUNCTION = ShellExecute(hDlg, "open", BYVAL VARPTR(mText), "", "", %SW_SHOWNORMAL)
    END FUNCTION

    ------------------
    [email protected]

    [This message has been edited by Eddy Van Esch (edited September 20, 2001).]
    Eddy

  • #2
    Try to use a dynamic string instead of az * 50000
    Then use StrPtr() instead of VarPtr()..


    ------------------
    hellobasic

    Comment


    • #3
      Originally posted by Edwin Knoppert:
      Try to use a dynamic string instead of az * 50000
      Then use StrPtr() instead of VarPtr()..
      That's the way it was at first Edwin. Notice the code that is commented out.
      But it also had the same problem. I tried with the ASCIIZ string because 'ShellExecute'
      requires an ASCIIZ string as argument, as I noticed in the function declare in
      win32api.inc .
      Eddy

      ------------------
      [email protected]
      Eddy

      Comment


      • #4
        In your REPLACE, don't you need REPLACE ANY?

        The way it's written, only the first occurrence of the charcters will be replaced. Maybe something barfs if you leave the control characters in there. Longer message, greater chance for occrrence of control characters?


        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Originally posted by Michael Mattias:
          In your REPLACE, don't you need REPLACE ANY?
          Michael,
          Not really. The REPLACE statement replaces all occurrences of MatchString in MainString with
          NewString.
          Furthermore, in this demo, the messagetext consists of nothing but characters "a"
          without any control characters and the program still crashes..
          Thanks for your input though.
          Eddy


          ------------------
          [email protected]
          Eddy

          Comment


          • #6
            Code:
            [b]LOCAL mText AS ASCIIZ * 50000[/b]
            change to this...?
             mText = "mailto:" & "[email protected]" & "?" & _
                     "Subject=" & "Some subject" & _
                     "&Body="   & mStr 
            Perhaps it will work..?

            ------------------
            Fred
            mailto:[email protected][email protected]</A>
            http://www.oxenby.se

            Fred
            mailto:[email protected][email protected]</A>
            http://www.oxenby.se

            Comment


            • #7
              Fred,
              I hope I understood you correctly. I replaced this:
              Code:
                 mText = "mailto:" & "[email protected]" & "?"
                 mText = mText & "Subject=" & "Some subject"
                 mText = mText & "&Body="   & mStr
              with this:
              Code:
                  mText = "mailto:" & "[email protected]" & "?" & _
                          "Subject=" & "Some subject" & _
                          "&Body="   & mStr
              while mText is still:
              LOCAL mText AS ASCIIZ * 50000
              I'm sorry,but no change in behavior...
              Thanks
              Eddy


              ------------------
              [email protected]
              Eddy

              Comment


              • #8
                Individual "lines" of message body text in an email (ie, between CR or CR/LF) should be
                less than 1000 characters (see the appropriate RFC for more info).


                ------------------
                Lance
                PowerBASIC Support
                mailto:[email protected][email protected]</A>
                Lance
                mailto:[email protected]

                Comment


                • #9
                  Can imagine the limitation is within the ShellExecute call. It was designed
                  for calling upp "associated" app's, etc, so guess the buffers for the parameters
                  has their limits - this causing the GPF on too long strings. Don't think
                  ShellExecuteEx can do it any better either.

                  Solution? Use own PB-written mail client, or do advanced stunt - send all
                  data except the body text, so mail program is started and cursor placed in
                  body text window, then find out handle of that window and send the text to
                  it via a WM_SETTEXT message call or the SetWindowText API.
                  Should be possible, I think..
                  ------------------
                  BTW, "LOCAL mText AS ASCIIZ * 50000" only allocates this space within your
                  program. LEN(mText) is what you actually send.


                  [This message has been edited by Borje Hagsten (edited September 20, 2001).]

                  Comment


                  • #10
                    Originally posted by Eddy Van Esch:
                    Fred,
                    I hope I understood you correctly. I replaced this:
                    Eddy, forget my post. I was not awake when I sent it.
                    Your code is perfectly good. (my minds were at fixed string, not asciiz buffer...)



                    ------------------
                    Fred
                    mailto:[email protected][email protected]</A>
                    http://www.oxenby.se

                    Fred
                    mailto:[email protected][email protected]</A>
                    http://www.oxenby.se

                    Comment


                    • #11
                      Lance,
                      I will check out your suggestion. Thanks!

                      Originally posted by Borje Hagsten:
                      Can imagine the limitation is within the ShellExecute call.
                      I begin to believe you are right Borje... So there's no hope for 'mailto:'...

                      Originally posted by Borje Hagsten:
                      Solution? Use own PB-written mail client,
                      I thought of that too, but 'mailto:' would have been easier, especially from an unexperienced
                      users point of view. He does not have to set his mailserver settings etc.
                      In a PB-written mail client, this would be the case, although not a gigantic problem I suppose.
                      A question on the side. Would an IT-responsible notice that the mail that is sent from
                      within his company, is sent by another mail program than the 'normal' mail program in
                      that company? (OE, Eudora,..) ?

                      Originally posted by Borje Hagsten:
                      or do advanced stunt - send all
                      data except the body text, so mail program is started and cursor placed in
                      body text window, then find out handle of that window and send the text to
                      it via a WM_SETTEXT message call or the SetWindowText API.
                      Should be possible, I think..
                      That's far beyond my programming capabilities Borje .
                      I bet you could do it in a flash...
                      Anyway, Thanks all for your suggestions!!!
                      Kind regards
                      Eddy




                      ------------------
                      [email protected]
                      Eddy

                      Comment


                      • #12
                        Use 'Byval' StrPtr()



                        ------------------
                        hellobasic

                        Comment


                        • #13
                          posted a small sample to source code forum that shows one way of doing it.
                          works fine with my netscape 4.6 here, but no guarantees for other app's.
                          see: http://www.powerbasic.com/support/pb...ad.php?t=23154

                          note: in win95/98, there is a 16-bit limit for text length in edit controls.


                          ------------------

                          Comment


                          • #14
                            Originally posted by Borje Hagsten:
                            Posted a small sample to source code forum that shows one way of doing it.
                            Borje,
                            Your sample looks awesome!!!! Will try it with Eudora as soon as I am on my
                            'PB'-pc !!!
                            Don't know how you pulled this one out of your sleeve so fast. I bet you
                            even type faster than you think
                            Thanks for once again a fine piece of sample code!
                            Kind regards
                            Eddy

                            ------------------
                            [email protected]

                            [This message has been edited by Eddy Van Esch (edited September 20, 2001).]
                            Eddy

                            Comment


                            • #15
                              originally posted by borje hagsten:
                              posted a small sample to source code forum that shows one way of doing it.
                              works fine with my netscape 4.6 here, but no guarantees for other app's.
                              see: http://www.powerbasic.com/support/pb...ad.php?t=23154
                              borje,
                              your program does not work with eudora and outlook express.
                              i changed the idstring. eudora seems to have difficulties with the tabs.
                              it now works with eudora but still not with outlook express... probably
                              also not with outlook.. as usual it's the m$ software that gives troubles.
                              would there be a workaround for oe..?
                              kind regards
                              eddy
                              Code:
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              ' demo of sendmymail function that handles long body text in mail,
                              ' since shellexecute can fail if text is too long (like > 1.4 kb..)
                              ' only tested with netscape 4.6
                              ' demonstrates how to find a child window in any running app' and
                              ' get/set own text to it. look and see - can be base for doing other
                              ' fun hacks in windows too..     public domain by borje hagsten, sept 2001
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              #compile exe
                              #include "win32api.inc"
                              
                              global ghmailprog as long, ghbodytextwindow as long, gssubject as string
                              
                              declare callback function dlgproc() as long
                              declare function enumwindowsproc(byval hwnd as long, byval lparam as long) as long
                              declare function enumchildsproc(byval hwnd as long, byval lparam as long) as long
                              declare function sendmymail(byval hdlg as long, _
                                                          byval mailto as string, _
                                                          byval subject as string, _
                                                          byval bodytext as string) as long
                              
                              $idstring = "aaaaa---==="
                              
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              ' main entrance
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              function pbmain () as long
                               local hdlg as long
                              
                                dialog new 0, "long mail test..",,, 130, 30, %ws_caption or %ws_sysmenu, 0 to hdlg
                                control add button, hdlg, %idok, "&send mail",   4,  4, 60, 14
                                control add button, hdlg, %idcancel, "&cancel", 64,  4, 60, 14
                              
                                dialog show modal hdlg call dlgproc
                              end function
                              
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              ' main dialog's callback procedure
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              callback function dlgproc() as long
                                dim i as long
                                if cbmsg = %wm_command then
                                   if cbctl = %idok then
                                      local stxt as string
                                      'stxt = repeat$(1000, "send more money.. " + $crlf) 'test with a 20,000 byte string
                                      stxt = "
                                      for i =1 to 1000
                                          stxt = stxt & "send money to borje" & str$(i) + $crlf
                                      next i
                                      call sendmymail(cbhndl, "[email protected]", "stupid subject..", stxt)
                              
                                   elseif cbctl = %idcancel then
                                      dialog end cbhndl
                                   end if
                                end if
                              end function
                              
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              ' sendmymail starts default mail program, passes on address and then
                              ' enumerates all windows and looks for proper text field to paste the
                              ' body text into. reason for this - long text fails with shellexecute.
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              function sendmymail(byval hdlg as long, _
                                                  byval mailto as string, _
                                                  byval subject as string, _
                                                  byval bodytext as string) as long
                              
                                local cnt as long, mtext as asciiz * 1000
                              
                                mtext = "mailto:"   & mailto & _
                                        "?subject=" & subject & _
                                        "&body="    & $idstring  'send id string for body text window
                              
                                if shellexecute(hdlg, "open", mtext, ", ", %sw_shownormal) > 32 then ' 'if success
                                   gssubject = subject                             'tell global string what subject to look for
                              
                                   'note:  following loop is not the best/safest way to find the mail program/body text window,
                                   'but can work fine for own use. probably not wise to rely on it for public use, though.
                                   'note2: since we set the text via api call, no need to convert anything in text..
                                   sleep 1000     'wait for mail program to finish
                                   do                                              'look for the mail program..
                                      sleep 100                                    'take a 0.1 second break between each attempt
                                      enumwindows codeptr(enumwindowsproc), 0      'enumerate all open windows
                                      if ghmailprog then                           'we got one with correct caption,
                                         enumchildwindows ghmailprog, codeptr(enumchildsproc), 0 'enumerate its childs
                                         exit do                                            'and exit this loop
                                      end if
                                      incr cnt                                     'still nothing found - increase counter
                                   loop until cnt = 200                            'try 100 times (ten seconds), then bail out
                              
                                   if ghbodytextwindow then                        'if we found correct child window in mail program
                                      sendmessage ghbodytextwindow, %wm_settext, 0, byval strptr(bodytext) 'set the text
                                   end if
                                end if
                              
                              end function
                              
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              ' enumerate running app's - look for caption containing subject string
                              '(note: only tested with netscape, you may have to exeriment here..)
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              function enumwindowsproc(byval hwnd as long, byval lparam as long) as long
                                local ztxt as asciiz * 260
                              
                                getwindowtext hwnd, ztxt, 260
                              
                                if len(ztxt) and instr(ztxt, gssubject) then  'look for the subject in the window's caption
                                   ghmailprog = hwnd            'assign current hwnd to global variable
                                   function = 0 : exit function 'return zero to break enumeration and exit
                                end if
                              
                                function = 1
                              end function
                              
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              ' enumerate child windows - look for identification string (5 tabs)
                              ' note: i have only tested this with netscape 4.6 - don't know if it
                              ' works with other versions/other mail programs.
                              ' note2: one can also use getclassname and look for a specific control
                              ' class, like edit, listbox and combobox, etc. not done here, because
                              ' we can't be sure searched window is a standard control..
                              '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                              function enumchildsproc(byval hwnd as long, byval lparam as long) as long
                                local ztxt as asciiz * 20
                              
                                sendmessage hwnd, %wm_gettext, 20, varptr(ztxt) 'get child window's text
                              
                                'if left$(ztxt, len($idstring)) = $idstring then 'look for id string
                                if instr(ztxt,$idstring) > 0 then 'look for id string
                                   ghbodytextwindow = hwnd      'assign current hwnd to global variable
                                   function = 0 : exit function 'return zero to break enumeration and exit
                                end if
                              
                                function = 1
                              end function
                              ------------------
                              [email protected]
                              Eddy

                              Comment


                              • #16
                                Well, it isn't called "MS Outlocked" for nothing..

                                I reluctantly started MSO and looked at the class name for the edit part,
                                and it is "INTERNET EXPLORER SERVER". Seems impossible to reach inside it,
                                so I guess they have made a real advanced stunt there and encapsulated the
                                whole thing.

                                However, there are always ways to fool MS. One can use the clipboard, and
                                first copy the text and then look for main window handle, plus send a
                                Ctrl+V to paste the text into the window. Tested here and it worked.

                                To find MS Outlook's main window, look for classname "ATH_Note" when
                                enumerating main windows (in EnumWindowsProc). When/if found, simulate
                                a sendkeys statement, like: (place this at top in EnumWindowsProc)
                                Code:
                                  IF hWnd THEN
                                     LOCAL clName AS ASCIIZ * 100
                                     GetClassName hWnd, clName, 100
                                
                                     IF UCASE$(clName) = "ATH_NOTE" THEN
                                        'Simulate Key Press
                                        Keybd_Event %VK_CONTROL, 0, 0, 0
                                        Keybd_Event 86, 0, 0, 0             'V = ASC 86
                                 
                                        'Simulate Key Release
                                        Keybd_Event 86, 0, %KEYEVENTF_KEYUP, 0
                                        Keybd_Event %VK_CONTROL, 0, %KEYEVENTF_KEYUP, 0
                                        FUNCTION = 0 : EXIT FUNCTION
                                     END IF
                                  END IF
                                 
                                '---------------------------------------
                                ' ..and to copy the text to the clipboard:
                                '---------------------------------------
                                FUNCTION ClipboardPutText (BYVAL txt AS STRING) AS LONG
                                  LOCAL cbPtr AS LONG, hData AS LONG, Bytes AS LONG
                                 
                                  txt = txt + CHR$(0)                    ' make it an ASCIIz string
                                  Bytes = LEN(txt)                       ' get # of bytes to load
                                  IF Bytes < 2 THEN EXIT FUNCTION        ' if no bytes to load
                                 
                                  hData = GlobalAlloc(&H2002, Bytes)     ' get memory address of clipboard
                                  cbPtr = GlobalLock(hData)              ' lock and get pointer to data
                                  POKE$ cbPtr, txt                       ' paste the text into memory
                                  GlobalUnlock hData                     ' unlock memory
                                 
                                  IF ISFALSE OpenClipboard(0) THEN       ' if clipboard isn't available
                                    GlobalFree hData                     ' free up memory
                                    EXIT FUNCTION                        ' Return false
                                  END IF
                                 
                                  EmptyClipboard                         ' empty whatever's in there now
                                  SetClipboardData %CF_TEXT, BYVAL hData ' point the clipboard at it as text
                                  CloseClipboard                         ' release clipboard
                                 
                                  FUNCTION = %TRUE                       ' return true
                                END FUNCTION

                                ------------------

                                Comment


                                • #17
                                  Can't seem to get it working with M$ Outlook Express.. My programming skills
                                  do not reach far enough I'm afraid.
                                  I think the best thing for me to do is to write an e-mail client in PB.
                                  I probably can use the example that came with PB/DLL.
                                  The advantage is that it is independent of the users e-mail client. The
                                  (perhaps small) disadvantage is that the user must fill in his mail server data.
                                  Anyway, thanks Borje for your time and your example code. I'm sure this will be
                                  usefull for other applications!
                                  Kind regards
                                  Eddy


                                  ------------------
                                  [email protected]
                                  Eddy

                                  Comment


                                  • #18
                                    Finally I have been able to spend some time on my mailtoroblem.
                                    Thanks to Borjes code snippets and tips I have been able to put some code
                                    together that is able to send long mails in Eudora, Outlook Express (!) and
                                    Netscape Messenger.
                                    I have not been able to test with MS Outlook because I don't have it.
                                    Could someone of you who does have MS Outlook please test this program to see if it
                                    works??
                                    This program should open your default mail client, create a new mail and put
                                    some (long) text in the body of the mail...
                                    I would appreciate it if someone could test it with MS Outlook.
                                    Kind regards
                                    Eddy
                                    Code:
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    ' Demo of SendMyMail function that handles long body text in mail,
                                    ' since ShellExecute can fail if text is too long (like > 1.4 KB..)
                                    ' Ttested with Eudora 5.0, Outloop Express and Netscape Messenger.
                                    ' Based on code of Borje Hagsten, Sept 2001
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    #COMPILE EXE
                                    #INCLUDE "WIN32API.INC"
                                    '%DEBUGMODE = 1          'Thanks to Gregery d Engle for his debugger
                                    '#INCLUDE "DEBUGDLL.INC
                                    GLOBAL gsSubject AS STRING
                                    GLOBAL IDString     AS STRING
                                    GLOBAL MailDone     AS LONG
                                    
                                    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
                                    DECLARE FUNCTION EnumWindowsProc(BYVAL hWnd AS LONG, BYVAL lParam AS LONG) AS LONG
                                    DECLARE FUNCTION ClipboardPutText (BYVAL txt AS STRING) AS LONG
                                    DECLARE FUNCTION SendMyMail(BYVAL hDlg AS LONG, _
                                                                BYVAL mailTo AS STRING, _
                                                                BYVAL subject AS STRING, _
                                                                BYVAL bodyText AS STRING) AS LONG
                                    
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    ' Main entrance
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    FUNCTION PBMAIN () AS LONG
                                     LOCAL hDlg AS LONG
                                      IDString = "Eddy"
                                      DIALOG NEW 0, "Long mail test..",,, 130, 30, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
                                      CONTROL ADD BUTTON, hDlg, %IDOK, "&SEND MAIL",   4,  4, 60, 14
                                      CONTROL ADD BUTTON, hDlg, %IDCANCEL, "&CANCEL", 64,  4, 60, 14
                                    
                                      DIALOG SHOW MODAL hDlg CALL DlgProc
                                    END FUNCTION
                                    
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    ' Main dialog's callback procedure
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    CALLBACK FUNCTION DlgProc() AS LONG
                                      DIM i AS LONG
                                      IF CBMSG = %WM_COMMAND THEN
                                         IF CBCTL = %IDOK THEN
                                            LOCAL sTxt AS STRING
                                            sTxt = ""  'Fabricate some long text
                                            FOR i = 1 TO 1000
                                                sTxt = sTxt + "Greetings! " + STR$(i)
                                            NEXT i
                                            
                                            'Try to create a new mail in your default mail client
                                            CALL SendMyMail(CBHNDL, "[email protected]", "Some subject..", sTxt)
                                    
                                         ELSEIF CBCTL = %IDCANCEL THEN
                                            DIALOG END CBHNDL
                                         END IF
                                      END IF
                                    END FUNCTION
                                    
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    ' SendMyMail starts default mail program, passes on address and then
                                    ' enumerates all windows and looks for proper text field to paste the
                                    ' body text into. Reason for this - long text fails with ShellExecute.
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    FUNCTION SendMyMail(BYVAL hDlg AS LONG, _
                                                        BYVAL mailTo AS STRING, _
                                                        BYVAL subject AS STRING, _
                                                        BYVAL bodyText AS STRING) AS LONG
                                    
                                      LOCAL cnt AS LONG, mText AS ASCIIZ * 1000
                                    
                                      ClipboardPutText bodyText  'Put this text on the clipboard to paste it later..
                                    
                                      mText = "mailto:"   & mailTo & _
                                              "?Subject=" & subject & _
                                              "&Body="    & IDString  'This is not necessary anymore
                                              
                                      'call the infamous 'mailto:' command...
                                      IF ShellExecute(hDlg, "open", mText, "", "", %SW_SHOWNORMAL) > 32 THEN ' >32
                                         SLEEP 2000 'Wait for your mail client to open. Time could be shorter but it is dangerous... longer is safer
                                         gsSubject  = LCASE$(subject)
                                         MailDone = %False
                                         DO                                              'look for the mail program..
                                            EnumWindows CODEPTR(EnumWindowsProc), 0      'enumerate all open windows
                                            IF MailDone THEN EXIT DO                     'and exit this loop
                                            'Mailprogram not found... try again..
                                            INCR cnt
                                            SLEEP 500
                                         LOOP UNTIL cnt > 25                             'try 25 times, then bail out
                                      END IF
                                    
                                    END FUNCTION
                                    
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    ' enumerate running app's - look for caption
                                    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                    FUNCTION EnumWindowsProc(BYVAL hWnd AS LONG, BYVAL lParam AS LONG) AS LONG
                                      LOCAL zTxt AS ASCIIZ * 260
                                    
                                      GetWindowText hWnd, zTxt, 260 'Get windows caption
                                      
                                      'For Eudora, it is ok to check for the program name in the main windows caption. For OE and Netscape we have to look for
                                      'a window that has the mails subject in its caption. Reason is that these programs open a seperate window for a new mail
                                      zTxt = LCASE$(zTxt)
                                      IF zTxt<>"" AND INSTR(zTxt, "eudora")>0 OR _   'For Eudora
                                         INSTR(zTxt, gsSubject)>0 THEN               'For Outlook Express and Netscape Messenger: look for the subject in window's caption
                                            SLEEP 2000 'Wait for 'new mail' window to open
                                            SetForegroundWindow hWnd
                                            'SetFocus hWnd
                                            GOSUB PasteText
                                            FUNCTION = 0 : EXIT FUNCTION 'return zero to break enumeration and exit
                                      ELSE
                                          FUNCTION = 1 : EXIT FUNCTION
                                      END IF
                                      EXIT FUNCTION
                                      
                                        PasteText: 'Do a 'CTRL V' to the current window to paste clipboard text
                                            'Simulate Key Presses
                                            Keybd_Event 9, 0, 0, 0  'send TABs to skip 'to','cc' and 'subject' fields
                                            Keybd_Event 9, 0, 0, 0
                                            Keybd_Event 9, 0, 0, 0
                                            
                                            'Send CTRL V to paste clipboard text
                                            Keybd_Event %VK_CONTROL, 0, 0, 0
                                            Keybd_Event 86, 0, 0, 0 'V = ASC 86
                                    
                                            'Simulate Key Release
                                            Keybd_Event 86, 0, %KEYEVENTF_KEYUP, 0
                                            Keybd_Event %VK_CONTROL, 0, %KEYEVENTF_KEYUP, 0
                                            MailDone = %True
                                        RETURN
                                    END FUNCTION
                                    
                                    
                                    '---------------------------------------
                                    ' ..and to copy the text to the clipboard:
                                    '---------------------------------------
                                    FUNCTION ClipboardPutText (BYVAL txt AS STRING) AS LONG
                                      LOCAL cbPtr AS LONG, hData AS LONG, Bytes AS LONG
                                    
                                      txt = txt + CHR$(0)                    ' make it an ASCIIz string
                                      Bytes = LEN(txt)                       ' get # of bytes to load
                                      IF Bytes < 2 THEN EXIT FUNCTION        ' if no bytes to load
                                    
                                      hData = GlobalAlloc(&H2002, Bytes)     ' get memory address of clipboard
                                      cbPtr = GlobalLock(hData)              ' lock and get pointer to data
                                      POKE$ cbPtr, txt                       ' paste the text into memory
                                      GlobalUnlock hData                     ' unlock memory
                                    
                                      IF ISFALSE OpenClipboard(0) THEN       ' if clipboard isn't available
                                        GlobalFree hData                     ' free up memory
                                        EXIT FUNCTION                        ' Return false
                                      END IF
                                    
                                      EmptyClipboard                         ' empty whatever's in there now
                                      SetClipboardData %CF_TEXT, BYVAL hData ' point the clipboard at it as text
                                      CloseClipboard                         ' release clipboard
                                    
                                      FUNCTION = %TRUE                       ' return true
                                    END FUNCTION
                                    ------------------
                                    [email protected]



                                    [This message has been edited by Eddy Van Esch (edited October 02, 2001).]
                                    Eddy

                                    Comment

                                    Working...
                                    X