Problem searching elements into a email list

Hi all,

I’m stuck with a script with which I intend to search for a specific email in a list of emails. For this I have a specific ‘To’ (miguelpruebatest@yopmail.com) that I want to find and a subject (Configura tu contraseña para).
If both checks match I will open that email. See an attached image of the website (mailhog) below:

The code behing this is:

In this code each line with:

is an email from the list of three.

How could i get all the 3 emails, search one by one for the one of them that match both conditions ‘To’ + Subject?

I tried with several scripts but most of them usin Get WebElements but one i get the web element it came as a Selenium Object and i don’t know how to search inside this webelement for the ‘To’ or ‘Subject’ xpath to find the text and check it. If i try to Get Text for the whole Get Element i got al the text and i think this could be improved.

Below you can find one of my attemps :
*** Settings ***
Library SeleniumLibrary
Test Teardown Cerrar Browser
Resource …/…/Resources/Webtest.resource
Suite Teardown Cerrar Browser

  *** Variables ***
  ${MAILHOG_URL}  https://xxxx.com/#  # Cambia la URL si tu Mailhog está en otro puerto

  *** Test Cases ***
  Seleccionar Email Por Para Y Asunto
      [Documentation]  Este test selecciona un email específico basado en el 'para' y el 'asunto'
      Open Browser    ${MAILHOG_URL}    ${BROWSER}    options=${BROWSER_OPTIONS}
      Maximize Browser Window
      Wait Until Page Contains Element  //div[@class="msglist-message row ng-scope"]  10s
      
      ${emails}  Get WebElements  //div[@class="msglist-message row ng-scope"]
      FOR  ${email}  IN  @{emails}
         ${To}  Get Text  ${email}//div[@ng-repeat="to in message.Content.Headers['To']"]
         Run Keyword If  '${To}' == 'miguelpruebatest@yopmail.com'  Check Email Subject  ${email}
      END


  *** Keywords ***
  Check Email Subject
      [Arguments]  ${email}
      ${subject}  Get Text  ${email}//span[@class="subject unread ng-binding"]
      Run Keyword If  '${subject}' == 'Configura tu contraseña para'  Click Element  ${email}

But as you can see i got an error :
[ FAIL ] Element with locator '<selenium.webdriver.remote.webelement.WebElement (session="5cfa3b73e2147de07b12e868e0877e19", element="f.1D31626DCBCD399E95112D1F9E69F437.d.7BC609D0014E8EDADD9B9F8531E32AC9.e.192")>//div[@ng-repeat="to in message.Content.Headers['To']"]' not found cause i don’t know how to interact with the webElement to get the info inside it.

Hi,

Depending of the DOM structure, and precision of your email sender and subject, a solution would be to search directly for the xpath containing both information (as they are somehow “linked” in strutcure and position).
Below is a example, with 3 differents locators that you could adjust (you could even add the read/unread info):

Search Mail
    [Arguments]    ${email}    ${subject}
    # Locator1 with fixed email and subject
    VAR    ${EMAIL_LOCATOR1}    //div[text()="${email}"]/following::div//span[text()="${subject}"]
    
    # Locator2 with fixed email and subject, more precise //span based on class
    VAR    ${EMAIL_LOCATOR2}    //div[text()="${email}"]/following::div//span[contains(@class, 'subject') and text()="${subject}"]
    
    # Locator3 with fixed email more precise //span based on class, partial subject
    VAR    ${EMAIL_LOCATOR3}    //div[text()="${email}"]/following::div//span[contains(@class, 'subject') and contains(text(), "${subject}")]

    ${isMail}    Run Keyword And Return Status    Element Should Be Visible    ${EMAIL_LOCATOR3}
    IF    ${isMail}
        RETURN    ${EMAIL_LOCATOR3}
    ELSE
        Log    The expected mail is not available    WARN
    END 

The idea with WebElements is a good one, but this mean having loops that may take time, moreover if your email box is not cleared.
I had some solutions like this in the past to find lines in table/tbody, but finally went to a more straightforward solution that has better performances.

Regards
Charlie

1 Like

Hi Pablo,

To start with the html in this app is aweful and is not making your life easy, especially with the

  • having the ng-if email’s address above it’s div in the parent div
  • and the ng-repeat email’s div being inside the ng-if email’s div

If you have access to the dev’s give them a hard time over it. Really that should be 2 defects on the html generatiion

The way I’d approach this is to break it down to parts. first I’d create some partial xpaths variables like this:

VAR    ${expected_email}    miguelpruebatest@yopmail.com
VAR    ${expected_subject}    Configura tu contraseña para

VAR    ${xp_basemsg}    //div[contains(@class, 'msglist-message')]
VAR    ${xp_ngif}    div[contains(@class, 'ng-binding')]
VAR    ${xp_ngrepeat}    div//div[contains(@class, 'ng-binding')]
VAR    ${xp_subject}    div/span[contains(@class, 'subject')]

Next use Get Element Count to get a count of messages that match ${xp_basemsg}

Then use a FOR-IN-RANGE loop to iterate over the messages and get the email addresses and subject

once you have them you can either append them to a list, add them to a dictionary or use an if statement to take action immediately, depends what you want, but I’ll show the if statement in this example:

${msgcount}=    Get Element Count    ${xp_basemsg}
FOR    ${index}    IN RANGE    ${msgcount}
    ${To_ngif}=    Get Text    (${xp_basemsg})[${index}]/${xp_ngif}
    ${To_ngrepeat}=    Get Text    (${xp_basemsg})[${index}]/${xp_ngrepeat}
    ${subject}=    Get Text    (${xp_basemsg})[${index}]/${xp_subject}
    IF    '${To_ngif}' == '${expected_email}' and '${subject}' == '${expected_subject}'
        # matched ngif email and subject
        # do somethng
        BREAK  # exit FOR loop 
    END
    IF    '${To_ngrepeat}' == '${expected_email}' and '${subject}' == '${expected_subject}'
        # matched ngrepeat email and subject
        # do somethng
        BREAK  # exit FOR loop 
    END
END

Hopefully that’s helpful,

Dave.

1 Like

@coopernico46 According to this yopmail supports the IMAP protocol Access your Yopmail.com Account with IMAP, SMTP or POP3 - August 2024. So I would use an IMAP library for Robot Framework. For example robotframework-imaplibrary2 · PyPI

Hi Lukas,

The webmail client he’s trying to script is not from yopmail, I looked at that first, so perhaps he’s tasked with testing the email web-app and has just used yopmail to send emails to it?

Dave.

Ah I see, @coopernico46 is using MailHog. Still MailHog has a JSON API that you can use instead of the web UI.

2 Likes

Hi @damies13 , @CharlieScene , @falcon030
Thank you all for your support.
I finally realized that the email web app allows searching, so I decided to search the email first so that all the results in the table were all from the same ‘To’ and then just search the subject.

Anyway @CharlieScene’s approach helped me learn some tricks with xpath… @damies13’s approach is possibly the one I’ll end up adopting.

Many thanks to all of you

3 Likes