A bit commented;
OPEN C1
-- Fetch first result and throw it away since next fetch will be done
-- before using the values
FETCH NEXT FROM C1 INTO
@sronum, @transdate,@item,@desc, @days, @email, @NAME
-- If the fetch went well, loop
WHILE @@FETCH_STATUS = 0
BEGIN
-- Fetch the next row and ignore if it went well for now
FETCH NEXT FROM C1 INTO
@sronum, @transdate,@item,@desc,@days, @email, @NAME
set @email = 'internal test email address'
set @subject = 'ADV Return is 30 days past due'
set @body = 'Dear ' + @name + ', </br></br>' + more text
-- Send a mail to the possibly valid address
EXEC msdb.dbo.sp_send_dbmail
@recipients = @email
,@Body = @Body
,@subject = @Subject
,@body_format = 'html'
,@exclude_query_output = 1
-- Jump back to the start of the loop to check if the mail just sent
-- was supposed to be sent.
END
CLOSE C1
DEALLOCATE C1
The simplest fix is to move the second fetch after the email has been sent. That will check if the first result was valid, send a mail, fetch a new row and go back to the validity check to possibly send another mail.