Managing timer intervals using millis at random intervals
I do not really understand your problem. More specifically,
“currentMillis-previousMillisx will always return true” does not make
sense, as it is not a boolean expression (it's unsigned long).

Anyway, the technique shown in blinkWithoutDelay is the way to go. Here
is my (untested) version:

const int relay_count = 4;  // we have 4 relays
const int relay_pins[relay_count] = {2, 3, 4, 5};
const unsigned long durations[relay_count] = {30000, 20000, 15000, 10000};
bool sms_received();  // you implement this one

void loop()
{
    static int current_relay = -1;  // meaning: no active relay
    static unsigned long last_switch;
    unsigned long now = millis();

    // If no relay is active, wait for an SMS.
    if (current_relay == -1) {
        if (sms_received()) {
            // Switch on first relay.
            current_relay = 0;
            digitalWrite(relay_pins[current_relay], HIGH);
            last_switch = now;
        }
    }

    // Otherwise, switch relays when it is time to do so.
    else if (now - last_switch &gt;= durations[current_relay]) {
        digitalWrite(relay_pins[current_relay], LOW);
        if (++current_relay == relay_count) {
            current_relay = -1;  // no active relay
        } else {
            digitalWrite(relay_pins[current_relay], HIGH);
            last_switch = now;
        }
    }
}


BTW, you did not specify what should happen if you receive an SMS while
one of the relays is active. I assume the SMS are only acknowledged when
no relay is active. Otherwise you would have to change the code.